Continued looking at properties in D - interfaces and constraints
mikey via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Wed Oct 12 13:40:57 PDT 2016
On Wednesday, 12 October 2016 at 08:36:43 UTC, Jonathan M Davis
wrote:
> That's exactly what it does. Having no contract is considered
> to be equivalent to having an empty contract. So, because an
> empty contract will never fail, not having an in contract in
> the base class (or interface) function is equivalent to not
> having any in contracts anywhere in the inheritance chain,
> which is pretty annoying. The ||ing and &&ing done with in and
> out contracts and inheritance is critical to having contracts
> work correctly with inheritance. And in contracts work properly
> when each level declares one, but it probably would be better
> if having an in contract were illegal if the base class didn't
> have one, since then you'd at least avoid accidentally having
> an in contract that's pointless. out contracts shouldn't have
> any of these problems though, since they're &&ed, and &&ing
> with true doesn't change anything. Missing in contracts
> definitely is an easy way to introduce bugs into your contracts
> though.
>
> - Jonathan M Davis
OK I'm somewhat struggling with this concept.
As I see it the "in" contract can only place a limit on what
values are valid to come in to the method. I could maybe see some
questionable argument to make any contract for values coming into
the method a subset of the previous valid values, but what you
are describing is the opposite: that each contract has to be a
superset of all the previous contracts for valid values!
This seems limiting at best, but worse completely at odds with
the concept of inheritance building from the most general to the
most specific case.
Say I have worker:
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;
}
}
class CEO : Worker {
private:
uint _wage = 1_000_000;
public:
override @property uint wage() { return _wage; }
override @property void wage(uint wage)
in {
enforce(wage >= 1_000_000 && wage <= 1_000_000_000);
} body {
_wage = wage;
}
}
void main() {
auto worker = new Worker;
assertThrown( worker.wage = 9_999 );
assertThrown( worker.wage = 1_000_000_001 );
assertNotThrown( worker.wage = 10_000 );
assertNotThrown( worker.wage = 1_000_000_000 );
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
auto ceo = new CEO;
assertThrown( ceo.wage = 9_999 );
assertThrown( ceo.wage = 1_000_000_001 );
assertNotThrown( ceo.wage = 10_000 ); // BAD - no throw
assertNotThrown( ceo.wage = 1_000_000_000 );
}
More information about the Digitalmars-d-learn
mailing list