digitalmars.D.learn - Can I make a variable public and readonly (outside where was declared)
- AsmMan (42/42) Sep 26 2014 I know I can combine it by making an extra variable plus a
- Gary Willoughby (9/51) Sep 26 2014 I think the extra variable and the properties are the way to go
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (65/68) Sep 26 2014 That's the proper way of doing it in D.
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (25/67) Sep 26 2014 The closest you can get is probably this:
- bearophile (5/14) Sep 26 2014 You can call them a and a_. Why are you not recommending this
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (17/30) Sep 26 2014 Don't know, it feels hacky. And I really don't like the two
- Steven Schveighoffer (17/26) Sep 26 2014 Hm.. that doesn't provide readonly access to either a or b.
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (4/27) Sep 27 2014 Yes, that's what I originally intended. Just forgot the const,
- Steven Schveighoffer (3/5) Sep 27 2014 I wondered... ;)
- AsmMan (28/57) Sep 27 2014 This is really a loot cool and works. Thanks. If private in D had
I know I can combine it by making an extra variable plus a property like this: class Foo { private int a_; void do_something1() { a_ = baa(); } void do_something2() { if(cond) a_ = baa2(); } property int a() { return a; } } limited knowledge. I don't do much OOP, maybe it's possible and I don't know. I'm using property to make 'a' accessible and readonly at same time but I wanted to do that without this a_ extra variable, i.e, only the methods within the Foo class can assign a new value to a but a instance of Foo can't. An imaginary code example: class Foo { public MAGIC_HERE int a; void do_something1() { a = baa(); } void do_something2() { if(cond) a = baa2(); } } And then: Foo f = new Foo(); writeln(f.a); // output value of a f.a = 10; // compile error: a is readonly outside Foo's methods. I hope it's clear (sorry for por English)
Sep 26 2014
On Friday, 26 September 2014 at 17:16:04 UTC, AsmMan wrote:I know I can combine it by making an extra variable plus a property like this: class Foo { private int a_; void do_something1() { a_ = baa(); } void do_something2() { if(cond) a_ = baa2(); } property int a() { return a; } } limited knowledge. I don't do much OOP, maybe it's possible and I don't know. I'm using property to make 'a' accessible and readonly at same time but I wanted to do that without this a_ extra variable, i.e, only the methods within the Foo class can assign a new value to a but a instance of Foo can't. An imaginary code example: class Foo { public MAGIC_HERE int a; void do_something1() { a = baa(); } void do_something2() { if(cond) a = baa2(); } } And then: Foo f = new Foo(); writeln(f.a); // output value of a f.a = 10; // compile error: a is readonly outside Foo's methods. I hope it's clear (sorry for por English)I think the extra variable and the properties are the way to go and it's the idiomatic way. In fact that's the reason properties are there. Saying that though, you can achieve what you want implementing a little more code using opDispatch. opDispatch intercepts calls to undefined members and deals with them, in this case forwarding to a private variable. http://dlang.org/operatoroverloading.html#dispatch
Sep 26 2014
On 09/26/2014 10:16 AM, AsmMan wrote:I know I can combine it by making an extra variable plus a property like this:That's the proper way of doing it in D. If it's too much work, it is possible to take advantage of mixins to reduce the boilerplate. I found the following code among my D samples; it must have been found on these forums. Defining without "set" would disallow the setter: alias AutoImplementedProperty!(string, "get") title; The code: import std.stdio; class Bar { alias AutoImplementedProperty!(string, "get", "set") title; } template AutoImplementedProperty(T, args...) { import std.typetuple; property { private T _name; static if (args.length) { static if (staticIndexOf!("get", args) > -1) { public T AutoImplementedProperty() { return _name; } } static if (staticIndexOf!("set", args) > -1) { public void AutoImplementedProperty(T value) { _name = value; } } } } } void main(string[] args) { Bar a = new Bar(); a.title = "asf"; writeln(a.title); return; }I wanted to do that without this a_ extra variableIf the value is set only once and it is known during construction, it is indeed mark the variable public const: import std.stdio; class Foo { public const int a; this (int x) { a = 2 * x; } } void main() { Foo f = new Foo(21); writeln(f.a); // output value of a Foo f2 = f; // copy works f2 = f; // assignment works // f.a = 10; // compile error: a is readonly outside Foo's methods. } Ali
Sep 26 2014
On Friday, 26 September 2014 at 17:16:04 UTC, AsmMan wrote:I know I can combine it by making an extra variable plus a property like this: class Foo { private int a_; void do_something1() { a_ = baa(); } void do_something2() { if(cond) a_ = baa2(); } property int a() { return a; } } limited knowledge. I don't do much OOP, maybe it's possible and I don't know. I'm using property to make 'a' accessible and readonly at same time but I wanted to do that without this a_ extra variable, i.e, only the methods within the Foo class can assign a new value to a but a instance of Foo can't. An imaginary code example: class Foo { public MAGIC_HERE int a; void do_something1() { a = baa(); } void do_something2() { if(cond) a = baa2(); } } And then: Foo f = new Foo(); writeln(f.a); // output value of a f.a = 10; // compile error: a is readonly outside Foo's methods. I hope it's clear (sorry for por English)The closest you can get is probably this: class Foo { private int a_; property int a() { return a_; } private property void a(int value) { a_ = value; } } You can then assign to `a` inside the class `Foo` _and_ inside its module (because `private` is always accessible from within the same module), while from other modules, it can only be read. But it's not exactly a read-only variable, because you cannot take an address from it, for example. Alternatively, you could create a union with a private and a public member with the same types, but I wouldn't recommend it. Besides, the members would need to have different names: class Foo { union { private int a; public int b; } }
Sep 26 2014
Marc Schütz:Alternatively, you could create a union with a private and a public member with the same types, but I wouldn't recommend it. Besides, the members would need to have different names: class Foo { union { private int a; public int b; } }You can call them a and a_. Why are you not recommending this solution? It looks cool (if it works). Bye, bearophile
Sep 26 2014
On Friday, 26 September 2014 at 17:52:58 UTC, bearophile wrote:Marc Schütz:Don't know, it feels hacky. And I really don't like the two different names, what's the point if I have to distinguish the two manually? Now yet another way came to my mind: struct PrivatelyWritableProperty(T) { private T value_; const(T) get() const { return value_; } private void opAssign(T value) { value_ = value; } alias get this; } class Foo { PrivatelyWritableProperty!int a; } But this looks even more fragile; there are probably some corner-cases where it doesn't work (for example, what happens when someone copies the containing struct?).Alternatively, you could create a union with a private and a public member with the same types, but I wouldn't recommend it. Besides, the members would need to have different names: class Foo { union { private int a; public int b; } }You can call them a and a_. Why are you not recommending this solution? It looks cool (if it works).
Sep 26 2014
On 9/26/14 1:36 PM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net>" wrote:Alternatively, you could create a union with a private and a public member with the same types, but I wouldn't recommend it. Besides, the members would need to have different names: class Foo { union { private int a; public int b; } }Hm.. that doesn't provide readonly access to either a or b. But it gave me an idea: class Foo { union { private int _a; public const int a; } void setA(int x) { _a = x; } } Hot damn! It works too :) Can't access _a from outside the module, can access a, but can't write it (even from within Foo). It's like an auto-inlined property function. I don't know how it would affect the optimizer, or the GC scanner. Unions are ugly things... -Steve
Sep 26 2014
On Friday, 26 September 2014 at 18:18:45 UTC, Steven Schveighoffer wrote:On 9/26/14 1:36 PM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net>" wrote:Yes, that's what I originally intended. Just forgot the const, and didn't even notice it after I reread it :-PAlternatively, you could create a union with a private and a public member with the same types, but I wouldn't recommend it. Besides, the members would need to have different names: class Foo { union { private int a; public int b; } }Hm.. that doesn't provide readonly access to either a or b. But it gave me an idea: class Foo { union { private int _a; public const int a; } void setA(int x) { _a = x; } }
Sep 27 2014
On 9/27/14 5:48 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net>"Yes, that's what I originally intended. Just forgot the const, and didn't even notice it after I reread it :-PI wondered... ;) -Steve
Sep 27 2014
On Friday, 26 September 2014 at 18:18:45 UTC, Steven Schveighoffer wrote:On 9/26/14 1:36 PM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net>" wrote:This is really a loot cool and works. Thanks. If private in D had was declared and not public to the entire module, I guess we could even do: class Foo { union { private int a_; public property int a() { return a_; } private property void a(int value) { a_ = value; } } //no one need knows the 'a_' (ugly?) identifier void setValue(int x) { a = x; } } And then Foo f = new Foo(); f.a = 10; // give a compile error becaus it is private and acessible within Foo class only BTW: I'm not sure about memory usage where using properties. But it is still cool.Alternatively, you could create a union with a private and a public member with the same types, but I wouldn't recommend it. Besides, the members would need to have different names: class Foo { union { private int a; public int b; } }Hm.. that doesn't provide readonly access to either a or b. But it gave me an idea: class Foo { union { private int _a; public const int a; } void setA(int x) { _a = x; } } Hot damn! It works too :) Can't access _a from outside the module, can access a, but can't write it (even from within Foo). It's like an auto-inlined property function. I don't know how it would affect the optimizer, or the GC scanner. Unions are ugly things... -Steve
Sep 27 2014