Suggested Change to Contract Syntax
Jonathan M Davis via Digitalmars-d
digitalmars-d at puremagic.com
Thu Mar 10 20:35:06 PST 2016
On Friday, 11 March 2016 at 04:17:51 UTC, jmh530 wrote:
> On Friday, 11 March 2016 at 01:45:36 UTC, Jonathan M Davis
> wrote:
>>
>> Sure, but if you're not using in/out contracts with a class,
>> you're not going to see how they interact with inheritance. To
>> mimic what they do, you'd have to duplicate the base class
>> contracts in the derived class and make sure that you ||ed the
>> in contracts correctly and &&ed the out contracts correctly,
>> which isn't very maintainable.
>>
>> - Jonathan M Davis
>
> If I'm understanding you correctly, you could still get the
> same behavior with something like below (though it isn't
> exactly right since Base.foo's in block would technically have
> a funky rule applied to it).
Yeah, you can do something like that and get it to work, but it
gets increasingly tricky, the more complicated the contracts are,
and it's pretty easy to screw it up. Certainly, it's far cleaner
and less error-prone to have it built into the language like we
do.
> After playing around with your example, I'm finding in/out
> blocks on derived classes to be tricky. I think I'm going to
> try to avoid putting myself in a situation where I would screw
> something up.
Yeah. Having complicated contracts is probably a bad idea in
general, but it gets far worse when inheritance is involved. And
you can give yourself some weird problems even with the built-in
help that D gives you. For instance, in my example, the derived
class' in contract was a looser version of the base class' in
contract, which is usually what you'd be looking to do, but the
way it works is that the bass class' in contract and the derived
class' in contract are ||ed. So, technically, you could make it
so that the two contracts are completely distinct or so that the
derived class' in contract is tighter, but what you ultimately
end up with is the two in contracts ||ed, whereas what most folks
will probably expect at a glance is that the derived class'
contract will be met. So, doing something like
base class: assert(i < 50);
derived class: assert(i < 10);
or
bass class: assert(i < 50);
derived class: assert(i > 50);
will quickly make it so that you could have a derived class
function which expects the derived class' in contract to be pass
when it doesn't, because what's tested is the ||ing or the
contracts not just the derived class contract.
So, ultimately, you still have to be familiar with how the in and
out contracts are supposed to work with inheritance to avoid
shooting yourself in the foot, but having it built in makes it so
that it's harder to screw it up. It just doesn't fix the whole
problem for you.
Regardless, I'd be _very_ careful with contracts and inheritance,
and having complicated contracts with inheritance seems a bit
suicidal.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list