Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
February 16, 2011 class invariants and property declarations | ||||
---|---|---|---|---|
| ||||
Hi, I just have started diving in D. Exploring the contract feature I stumbled upon the fact that a class invariant does not apply to properties: import std.stdio; void main(string[] args) { Time t = new Time(); t.hours = 24; // works; why? writeln("t.hours is ", t.hours); t.add(1); // triggers an assertion failure as expected writeln("t.hours is ", t.hours); } class Time { invariant() { assert( 0 <= hours && hours < 13); } @property int hours; public void add(int hours) { this.hours += hours; } } compiled using Digital Mars DMD (2.051 on Ubuntu 10.10) is given the following result: t.hours is 24 core.exception.AssertError@invarprop(13): Assertion failure ---------------- ./InVariantProperty() [0x8057ade] ./InVariantProperty() [0x804f7e6] ./InVariantProperty() [0x804cba3] ./InVariantProperty() [0x8049856] ./InVariantProperty() [0x804fa86] ./InVariantProperty() [0x8049869] ./InVariantProperty() [0x8049813] ./InVariantProperty() [0x804f9f2] ./InVariantProperty() [0x804f94c] ./InVariantProperty() [0x804fa36] ./InVariantProperty() [0x804f94c] ./InVariantProperty() [0x804f8f4] /lib/libc.so.6(__libc_start_main+0xe7) [0xa5cce7] ./InVariantProperty() [0x8049721] Should not a class invariant apply to properties, too? Kind regards Michael |
February 16, 2011 Re: class invariants and property declarations | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michael Engelhardt | On 16.02.2011 11:03, Michael Engelhardt wrote: > Hi, > I just have started diving in D. Exploring the contract feature I > stumbled upon the fact that a class invariant does not apply to properties: Welcome on board :) Invariant gets called on every public method call (at begin & end if I'm not mistaken). Now to properties, this is actually shouldn't be allowed: @property int hours; @property is a annotation applied to functions (getter/setter), to allow calling it with omitted () and a natural assign syntax like this: class Time { private: int _hours; public: //... @property int hours() { return _hours; } @property void hours(int newHours) { _hours = newHours; } } auto t = new Time(); t.hours = 5; // calls void hours(5) assert(t.hours == 5); //calls int hours() Now given that setter and getter are public methods they'd got the invariant called. > import std.stdio; > > void main(string[] args) { > Time t = new Time(); > t.hours = 24; // works; why? > writeln("t.hours is ", t.hours); > t.add(1); // triggers an assertion failure as expected > writeln("t.hours is ", t.hours); > } > > class Time { > invariant() { > assert( 0<= hours&& hours< 13); > } > @property int hours; > > public void add(int hours) { > this.hours += hours; > } > } > > compiled using Digital Mars DMD (2.051 on Ubuntu 10.10) is given the > following result: > > t.hours is 24 > core.exception.AssertError@invarprop(13): Assertion failure > ---------------- > ./InVariantProperty() [0x8057ade] > ./InVariantProperty() [0x804f7e6] > ./InVariantProperty() [0x804cba3] > ./InVariantProperty() [0x8049856] > ./InVariantProperty() [0x804fa86] > ./InVariantProperty() [0x8049869] > ./InVariantProperty() [0x8049813] > ./InVariantProperty() [0x804f9f2] > ./InVariantProperty() [0x804f94c] > ./InVariantProperty() [0x804fa36] > ./InVariantProperty() [0x804f94c] > ./InVariantProperty() [0x804f8f4] > /lib/libc.so.6(__libc_start_main+0xe7) [0xa5cce7] > ./InVariantProperty() [0x8049721] > > Should not a class invariant apply to properties, too? > > Kind regards > > Michael -- Dmitry Olshansky |
February 16, 2011 Re: class invariants and property declarations | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dmitry Olshansky | Dmitry Olshansky Wrote:
> Now to properties, this is actually shouldn't be allowed:
>
> @property int hours;
>
> @property is a annotation applied to functions (getter/setter), to allow calling it with omitted () and a natural assign syntax like this:
Why shouldn't it be allowed? While it provides no benefit it does document that it is a property.
|
February 16, 2011 Re: class invariants and property declarations | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On 16.02.2011 20:47, Jesse Phillips wrote: > Dmitry Olshansky Wrote: > >> Now to properties, this is actually shouldn't be allowed: >> >> @property int hours; >> >> @property is a annotation applied to functions (getter/setter), to allow calling it with omitted () and a natural assign syntax like this: > Why shouldn't it be allowed? While it provides no benefit it does document that it is a property. Well, it does not affect the code in any meaningful way. Also it's not the property per see it's data member, you can even take it's address. To me such 'features' that silently do nothing should be an error. As to document anything then the comment does it and without the phantom semantic load. -- Dmitry Olshansky |
February 16, 2011 Re: class invariants and property declarations | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On Wednesday, February 16, 2011 09:47:32 Jesse Phillips wrote: > Dmitry Olshansky Wrote: > > Now to properties, this is actually shouldn't be allowed: > > @property int hours; > > > > @property is a annotation applied to functions (getter/setter), to allow calling it with omitted () and a natural assign syntax like this: > Why shouldn't it be allowed? While it provides no benefit it does document that it is a property. Except that @property is for _functions_. You mark a function with @property so that it _acts_ like a variable. @property on a variable is _meaningless_. It would be like marking a variable nothrow. It makes no sense. Neither should be legal. The fact that a member variable is public makes it a property. @property on a member variable makes no sense. - Jonathan M Davis |
February 16, 2011 Re: class invariants and property declarations | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On Wed, 16 Feb 2011 12:47:32 -0500, Jesse Phillips <jessekphillips+D@gmail.com> wrote:
> Dmitry Olshansky Wrote:
>
>> Now to properties, this is actually shouldn't be allowed:
>>
>> @property int hours;
>>
>> @property is a annotation applied to functions (getter/setter), to allow calling it with omitted () and a natural assign syntax like this:
>
> Why shouldn't it be allowed? While it provides no benefit it does document that it is a property.
>
Regardless of this, you should be aware that an invariant is not called when a public field is changed/accessed, whether it's marked with @property or not. Only member functions invoke the invariant.
-Steve
|
February 17, 2011 Re: class invariants and property declarations | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | Jonathan M Davis Wrote:
> Except that @property is for _functions_. You mark a function with @property so that it _acts_ like a variable. @property on a variable is _meaningless_. It would be like marking a variable nothrow. It makes no sense. Neither should be legal. The fact that a member variable is public makes it a property. @property on a member variable makes no sense.
>
> - Jonathan M Davis
class Foo {
@property {
int min;
int hour() { return _hour;}
...
}
}
I agree that useless markings should usually be disallowed, but for me there is visual cues that @property provides and if I'm declaring a number of public fields/functions I'd want the present them in a similar manner.
|
February 17, 2011 Re: class invariants and property declarations | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On Thursday, February 17, 2011 10:39:20 Jesse Phillips wrote:
> Jonathan M Davis Wrote:
> > Except that @property is for _functions_. You mark a function with @property so that it _acts_ like a variable. @property on a variable is _meaningless_. It would be like marking a variable nothrow. It makes no sense. Neither should be legal. The fact that a member variable is public makes it a property. @property on a member variable makes no sense.
> >
> > - Jonathan M Davis
>
> class Foo {
> @property {
> int min;
> int hour() { return _hour;}
> ...
> }
> }
>
> I agree that useless markings should usually be disallowed, but for me there is visual cues that @property provides and if I'm declaring a number of public fields/functions I'd want the present them in a similar manner.
Except that @property on a variable does _nothing_. It's totally inappropriate. I really think that it should be a bug. It wouldn't make any sense to mark a variable as nothrow would it? A public member variable is both a property and nothrow by its very nature.
Now, sadly enough, if you replace @property with nothrow in the code above (and remove the ... and make sure that there's actually an _hour variable), it compiles just fine, so the compiler is being ridiculously lax about attributes that aren't valid.
- Jonathan M Davis
|
Copyright © 1999-2021 by the D Language Foundation