Thread overview | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
May 21, 2016 Is there a way to make a class variable visible but constant to outsiders, but changeable (mutable) to the class itself? | ||||
---|---|---|---|---|
| ||||
Is it possible to have a class which has a variable which can be seen from the outside, but which can only be modified from the inside? Something like: class C { int my_var = 3; // semi_const?? void do_something() { my_var = 4; } } And then in another file auto c = new C(); c.my_var = 5; // <<<- should trigger a compile-time error writeln("the value is ", c.my_var); // <<<- should print 3 c.do_something(); writeln("the value is ", c.my_var); // <<<- should print 4 Reading Alexandrescu's book suggests the answer is "no" (the only relevant type qualifiers are private, package, protected, public, and export, and none seem appropriate). (This effect could be simulated by making my_var into a function, but i don't want to do that.) TIA for any info! dan |
May 21, 2016 Re: Is there a way to make a class variable visible but constant to outsiders, but changeable (mutable) to the class itself? | ||||
---|---|---|---|---|
| ||||
Posted in reply to dan | On Saturday, 21 May 2016 at 17:32:47 UTC, dan wrote:
> Is it possible to have a class which has a variable which can be seen from the outside, but which can only be modified from the inside?
>
> Something like:
>
> class C {
> int my_var = 3; // semi_const??
> void do_something() { my_var = 4; }
> }
>
> And then in another file
>
> auto c = new C();
> c.my_var = 5; // <<<- should trigger a compile-time error
> writeln("the value is ", c.my_var); // <<<- should print 3
> c.do_something();
> writeln("the value is ", c.my_var); // <<<- should print 4
>
> Reading Alexandrescu's book suggests the answer is "no" (the only relevant type qualifiers are private, package, protected, public, and export, and none seem appropriate).
>
> (This effect could be simulated by making my_var into a function, but i don't want to do that.)
>
> TIA for any info!
>
> dan
class C {
int my_var() { return _my_var; }
int _my_var;
}
|
May 21, 2016 Re: Is there a way to make a class variable visible but constant to outsiders, but changeable (mutable) to the class itself? | ||||
---|---|---|---|---|
| ||||
Posted in reply to dan | On Saturday, 21 May 2016 at 17:32:47 UTC, dan wrote:
> Is it possible to have a class which has a variable which can be seen from the outside, but which can only be modified from the inside?
>
> Something like:
>
> class C {
> int my_var = 3; // semi_const??
> void do_something() { my_var = 4; }
> }
>
> And then in another file
>
> auto c = new C();
> c.my_var = 5; // <<<- should trigger a compile-time error
> writeln("the value is ", c.my_var); // <<<- should print 3
> c.do_something();
> writeln("the value is ", c.my_var); // <<<- should print 4
>
> Reading Alexandrescu's book suggests the answer is "no" (the only relevant type qualifiers are private, package, protected, public, and export, and none seem appropriate).
>
> (This effect could be simulated by making my_var into a function, but i don't want to do that.)
>
> TIA for any info!
>
> dan
You can create a const accessor for the variable. Then you can have it be mutable internally but const externally.
Class C
{
int _my_var = 2;
void setMyVarTo3() { _my_var = 3; }
@property const(int) my_var() { return _my_var; }
}
auto c = new C();
writeln(c.my_var); //Prints 2
c.setMyVarTo3();
writeln(c.my_var); //Prints 3
c.my_var = 4; //Error, cannot modify const(int)
|
May 21, 2016 Re: Is there a way to make a class variable visible but constant to outsiders, but changeable (mutable) to the class itself? | ||||
---|---|---|---|---|
| ||||
Posted in reply to dan | On Saturday, 21 May 2016 at 17:32:47 UTC, dan wrote:
> Is it possible to have a class which has a variable which can be seen from the outside, but which can only be modified from the inside?
>
> Something like:
>
> class C {
> int my_var = 3; // semi_const??
> void do_something() { my_var = 4; }
> }
>
> And then in another file
>
> auto c = new C();
> c.my_var = 5; // <<<- should trigger a compile-time error
> writeln("the value is ", c.my_var); // <<<- should print 3
> c.do_something();
> writeln("the value is ", c.my_var); // <<<- should print 4
>
> Reading Alexandrescu's book suggests the answer is "no" (the only relevant type qualifiers are private, package, protected, public, and export, and none seem appropriate).
>
> (This effect could be simulated by making my_var into a function, but i don't want to do that.)
>
> TIA for any info!
>
> dan
class C {
private:
int my_var_ = 3; // semi_const
@property final void my_var(int x){ ///private setter
this.my_var_ = x;
}
public:
@property final int my_var()const{ ///public getter
return my_var_;
}
void do_something() {
my_var = 4;
}
}
|
May 21, 2016 Re: Is there a way to make a class variable visible but constant to outsiders, but changeable (mutable) to the class itself? | ||||
---|---|---|---|---|
| ||||
Posted in reply to vit | Thanks Vit, Meta, and Yuxuan for your speedy help! So 3 pieces to put together, function, const, and @property (and i guess final for protection against subclasses). |
May 22, 2016 Re: Is there a way to make a class variable visible but constant to outsiders, but changeable (mutable) to the class itself? | ||||
---|---|---|---|---|
| ||||
Posted in reply to dan | On Saturday, 21 May 2016 at 19:17:00 UTC, dan wrote:
> Thanks Vit, Meta, and Yuxuan for your speedy help!
>
> So 3 pieces to put together, function, const, and @property (and i guess final for protection against subclasses).
Minimally, there are two pieces to this: a private member variable and a function.
class Foo {
private int _myVar;
int myVar() { return _myVar; }
}
The private is necessary because class members in D are all public by default. If it isn't there, then _myVar can be directly modified outside of the module. Be aware, though (if you aren't already), that private members *are* accessible outside of the class in the same module, e.g.:
module foo;
class Foo {
private int _myVar;
int myVar() { return _myVar; }
}
void printMyVar() {
import std.stdio : writeln;
auto f = new Foo;
writeln(f);
}
As for 'const' and '@property', neither is strictly a requirement to implement this idiom. Adding const means that you can call the function through const references, but if that's not something you want to allow for some reason, then don't add it.
@property right now doesn't really do anything other than allow for self-documenting code. Perhaps one day it will be fully implemented and require callers to drop the parentheses in calls to @property functions, but for now it doesn't do that. Use it as much as you want, but just understand it isn't necessary for the functionality you are after.
|
May 22, 2016 Re: Is there a way to make a class variable visible but constant to outsiders, but changeable (mutable) to the class itself? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Sunday, 22 May 2016 at 03:06:44 UTC, Mike Parker wrote:
> As for 'const' and '@property', neither is strictly a requirement to implement this idiom. Adding const means that
Oh, and the same holds true for final, of course. It's probably what you want most of the time, but it isn't strictly necessary for the idiom.
|
May 22, 2016 Re: Is there a way to make a class variable visible but constant to outsiders, but changeable (mutable) to the class itself? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Sunday, 22 May 2016 at 03:06:44 UTC, Mike Parker wrote:
> On Saturday, 21 May 2016 at 19:17:00 UTC, dan wrote:
>> Thanks Vit, Meta, and Yuxuan for your speedy help!
>>
>> So 3 pieces to put together, function, const, and @property (and i guess final for protection against subclasses).
>
> Minimally, there are two pieces to this: a private member variable and a function.
>
> class Foo {
> private int _myVar;
> int myVar() { return _myVar; }
> }
>
> The private is necessary because class members in D are all public by default. If it isn't there, then _myVar can be directly modified outside of the module. Be aware, though (if you aren't already), that private members *are* accessible outside of the class in the same module, e.g.:
>
> module foo;
>
> class Foo {
> private int _myVar;
> int myVar() { return _myVar; }
> }
>
> void printMyVar() {
> import std.stdio : writeln;
> auto f = new Foo;
> writeln(f);
> }
>
> As for 'const' and '@property', neither is strictly a requirement to implement this idiom. Adding const means that you can call the function through const references, but if that's not something you want to allow for some reason, then don't add it.
>
> @property right now doesn't really do anything other than allow for self-documenting code. Perhaps one day it will be fully implemented and require callers to drop the parentheses in calls to @property functions, but for now it doesn't do that. Use it as much as you want, but just understand it isn't necessary for the functionality you are after.
Const *is* necessary to prevent _myVar being written to through code like:
f.myVar = 4;
Of course this isn't necessary for value types, but for reference types.
It's also useful for value types, IMO, for preventing someone from doing this:
f.myVar = 4;
And wondering why the code has no effect.
|
May 22, 2016 Re: Is there a way to make a class variable visible but constant to outsiders, but changeable (mutable) to the class itself? | ||||
---|---|---|---|---|
| ||||
Posted in reply to dan | On Saturday, 21 May 2016 at 17:32:47 UTC, dan wrote:
> Is it possible to have a class which has a variable which can be seen from the outside, but which can only be modified from the inside?
>
> Something like:
>
> class C {
> int my_var = 3; // semi_const??
> void do_something() { my_var = 4; }
> }
>
Yes, I prefer this idiom:
class C
{
union
{
private int var_rw;
public const(int) var_ro;
}
}
|
May 23, 2016 Re: Is there a way to make a class variable visible but constant to outsiders, but changeable (mutable) to the class itself? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | On Sunday, 22 May 2016 at 19:29:59 UTC, Meta wrote: > Const *is* necessary to prevent _myVar being written to through code like: > > f.myVar = 4; > > Of course this isn't necessary for value types, but for reference types. > I was referring specifically to marking the function const, not the return type. Marking the return type const is highly context-dependent. It's perfectly reasonable to return a non-const class reference from a getter property. As long as the internal reference is private, it isn't going to be overwritten externally without a setter property. I don't see how it could be considered necessary. For a pointer, sure, to prevent *(bar.fooVer) = Foo(10). But for class references it's only necessary if you don't want the returned instances members to be modified. > It's also useful for value types, IMO, for preventing someone from doing this: > > f.myVar = 4; > > And wondering why the code has no effect. The compiler already gives an error message describing the problem: Error: function mod.Foo.myVar () is not callable using argument types (int) How does const help here? |
Copyright © 1999-2021 by the D Language Foundation