optional feature with contract inheritance? (design question)

Jonathan M Davis jmdavisProg at gmail.com
Sat Feb 27 11:09:26 PST 2010


Lutger wrote:

> What do you think of the following use of contracts?
> 
> class Base
> {
>     void useFeatureA()
>     in { assert(false, "Base does not implement feature A"); }
>     body
>     { 
>         /* throw here? */
>     }
> 
>     bool hasFeatureA()
>     {
>         return false;
>     }
> }
> 
> class Derived : Base
> {
>     override void useFeatureA()
>     in { assert(true); }
>     body
>     { 
>         /* do feature A */
>     }
> 
>     override bool hasFeatureA()
>     {
>         return true;
>     }
> }
> 
> In .NET this is supposedly called the optional feature pattern,
> recommended to use if you want to prevent factoring into too many
> interfaces. In .NET A.useFeatureA would just throw of course.
> 
> Adding preconditions to functions in a derived class loosens the contract,
> or adds to the set of acceptable inputs so to speak. In this case, the
> polymorphic type of the object is considered as the (sole) input.
> 
> Does it make sense? Is this a good/bad/ugly way of using contracts?

Actually, I don't think that there's much point to the contracts here. 
assert(true) in the second one is pointless. It will always pass. And 
assert(false ...) in the second one doesn't really add anything either. 
It'll throw an AssertError when the function itself would have thrown an 
exception anyway (albeit presumably of a different type).

Generally, I speaking, I think that having functions which override 
functions from a base class and throw if they're used is a bad design. It 
may be that it makes perfect sense in some contexts, but generally, I'd 
consider it a very bad idea. Personally, I hate it when APIs do that.

Regardless of whether you consider that a good or bad idea though, there's 
no point in adding contracts into it. They don't add anything. If the 
feature is supported by the class, then no exception gets thrown. If it 
isn't, then an exception gets thrown. All adding asserts in preconditions 
does is make it an AssertError instead of whatever kind of exception you're 
throwing in the body. It doesn't add anything.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list