Broken contract programing
Idan Arye via Digitalmars-d
digitalmars-d at puremagic.com
Wed May 13 05:16:38 PDT 2015
On Wednesday, 13 May 2015 at 10:51:09 UTC, iackhtak wrote:
> There was discussion about broken contract programing. One
> thing was "in" contract within inheritance. If you add different
> "in"-contract in overridden parent and derived function only one
> will be checked.
Not "only one" is checked - they are checked until one passes. If
only the last one passes all of them need to be checked.
> I thought that solution is to ban "in"-contract for derived
> function. "In"-contract says what you can pass. If you want to
> accept input without any constraints you can't add new
> in inherited stuff because your inherited stuff can by used in
> any context where base thing can. Within this context any
> arguments can be passed. This way adding new constraints on
> brakes Liskov substitution principle and have to be banned.
> Theoretically it can be allowed to loose contract(and extend
> interface) but the thing looks hard to implement.
I think the `in` contracts check should be statically dispatched,
so that only the contracts relevant to the reference-type you are
calling the method from will be checked.
Take http://dpaste.dzfl.pl/9ec5962518391 for example. The first
time I call `a.foo(15)` it rightfully fails, because `A.foo` only
accepts values smaller than 10. When I call `b.foo(15)` it
rightfully succeeds, because `B.foo` loosens the contract to
accept values smaller than 20.
The problem is that the second call to `a.foo(15)` succeeds. `a`
contains `B`, but the user should not rely on that! LSP says that
we should be able to use `B`s like they were `A` - not `A`s like
they were `B`s. The `in` contract should make sure the user of
the code is using it correctly, but it's not doing it's job here
because it allows us to call `A.foo` with 15, just because our
`A` reference happens to point to an instance of `B`.
More information about the Digitalmars-d