Continued looking at properties in D - interfaces and constraints

ag0aep6g via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Oct 12 14:30:25 PDT 2016


On 10/12/2016 10:40 PM, mikey wrote:
>     import std.exception;
>
>     class Worker {
>     private:
>         uint _wage = 10_000;
>
>     public:
>         @property uint wage() { return _wage; }
>         @property void wage(uint wage)
>         in {
>             enforce(wage >= 10_000 && wage <= 1_000_000_000);
>         } body {
>             _wage = wage;
>         }
>     }
>
>     class WageSlave : Worker {
>     private:
>         uint _wage = 10_000;
>
>     public:
>         override @property uint wage() { return _wage; }
>         override @property void wage(uint wage)
>         in {
>             enforce(wage >= 10_000 && wage <= 40_000);
>         } body {
>             _wage = wage;
>         }
>     }
[...]
>     void main() {
[...]
>         auto slave = new WageSlave;
>         assertThrown( slave.wage = 9_999 );
>         assertThrown( slave.wage = 1_000_000_001 );
>         assertNotThrown( slave.wage = 10_000 );
>         assertNotThrown( slave.wage = 1_000_000_000 ); // BAD - no throw
[...]
>     }

The behavior you expect would break substitutability [1]. Consider:

----
void f(Worker w)
{
     w.wage = 50_000; /* Contract of Worker says I can do this. */
}
void main()
{
     f(new Worker); /* Obviously ok. */
     f(new WageSlave); /* Must work. A WageSlave object must be usable 
as a Worker object. */
}
----


[1] https://en.wikipedia.org/wiki/Liskov_substitution_principle


More information about the Digitalmars-d-learn mailing list