Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
October 02, 2016 Getting consistent behavour for class properties | ||||
---|---|---|---|---|
| ||||
Hi, I'm experimenting with the behaviour of properties in D, as I am writing some classes that are being used in a mixture of const and non-const functions. I've found a couple of things that I'd just like to check. First perhaps I should say what I would expect from working with properties in a mixed const / non-const environment. * I expect getting a property to work for both const and non-const. * I expect setting a property to only work for non-const. I found that to get this behaviour I needed to declare any getter return type as well as the property function as "inout". This seemed to work for getter / setter function pairs as well as the "@property auto ref" idiom. I also noticed something that was unexpected to me as a beginner, that the getter / setter pairs are not valid with the "+=" operator but the "auto ref" is. I guess this is down to the way D interprets the syntax during compilation and the differences between how the 2 different implementations access the data. But it is none the less surprising that the flowing are not syntactically equivalent. t.val = t.val + 1; t.val += t.val; Anyway here is my test code: module test; class Test { private: int _val; public: @property inout(int) val() inout { return _val; } @property void val(int val) { _val = val; } @property auto ref inout(int) val2() inout { return _val; } } void test(Test t) { import std.stdio : writeln; writeln("--- test ----"); writeln("val: ", t.val); writeln("val2: ", t.val2); } void test2(in Test t) { import std.stdio : writeln; writeln("--- test 2 ----"); writeln("val: ", t.val); writeln("val2: ", t.val2); } void main() { auto t = new Test; //t.val += 100; // BAD - not an lvalue t.val = t.val + 100; test(t); t.val2 += 100; // OK test2(t); } |
October 02, 2016 Re: Getting consistent behavour for class properties | ||||
---|---|---|---|---|
| ||||
Posted in reply to mikey | On Sunday, 2 October 2016 at 14:26:46 UTC, mikey wrote:
> t.val = t.val + 1;
> t.val += t.val;
Sorry that should have of course read:
t.val = t.val + 1;
t.val += 1;
|
October 02, 2016 Re: Getting consistent behavour for class properties | ||||
---|---|---|---|---|
| ||||
Posted in reply to mikey | On Sunday, 2 October 2016 at 14:26:46 UTC, mikey wrote: > [...] Yeah, a property is quite different from a variable. In fact, a property may refer to a computed value, which may not have an address and as such cannot be modified: @property auto currentTimeMillis() { return currentTimeNanos/1000000; } So it is correct that `+=` doesn't work with properties, and neither does the "addressof" operator `&` (it returns the delegate). Having a getter property return by ref circumvents this issue, but has the drawback of bypassing any check that a setter property would do. If you want to use properties as getters/setters and also want compound assignments to work, you can easily achieve that with a wrapper template as this[1] one. [1] http://pastebin.com/38n0fEtF |
October 02, 2016 Re: Getting consistent behavour for class properties | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lodovico Giaretta | On Sunday, 2 October 2016 at 14:44:13 UTC, Lodovico Giaretta wrote:
> Yeah, a property is quite different from a variable. In fact, a property may refer to a computed value, which may not have an address and as such cannot be modified:
> [...]
> So it is correct that `+=` doesn't work with properties, and neither does the "addressof" operator `&` (it returns the delegate). Having a getter property return by ref circumvents this issue, but has the drawback of bypassing any check that a setter property would do.
There is already a degree of transparency with how properties being handled for example in allowing properties to be an lvalue if they have a setter.
t.val = 42;
I can understand that on an implementation level it might be simpler to interpret the 2 statements differently but it would seem much more intuitive to me if the syntactic sugar for properties were extended out to allow statements such as:
t.val += 1;
Where there is a getter and setter available.
To my mind at least the ideal would be for properties to act as close as possible to member variables.
It is however good to see that it's possible to wrap functions to provide some of this behaviour.
|
October 02, 2016 Re: Getting consistent behavour for class properties | ||||
---|---|---|---|---|
| ||||
Posted in reply to mikey | On Sunday, 2 October 2016 at 17:10:58 UTC, mikey wrote:
> There is already a degree of transparency with how properties being handled for example in allowing properties to be an lvalue if they have a setter.
>
> t.val = 42;
Actually, this is not specific to properties, as it also works on "standard" methods, if they have a single parameter:
import std.stdio;
void main()
{
writeln = 42;
}
|
October 03, 2016 Re: Getting consistent behavour for class properties | ||||
---|---|---|---|---|
| ||||
Posted in reply to mikey | I suppose that's https://issues.dlang.org/show_bug.cgi?id=8006 |
October 09, 2016 Re: Getting consistent behavour for class properties | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | On Monday, 3 October 2016 at 14:05:24 UTC, Kagamin wrote:
> I suppose that's https://issues.dlang.org/show_bug.cgi?id=8006
Yes, exactly. Although, I don't see why they wrap it in a struct in the example as this seems to me to just obfuscate the issue.
|
Copyright © 1999-2021 by the D Language Foundation