[Zope3-dev] Interface declaration API

Phillip J. Eby pje@telecommunity.com
Tue, 11 Mar 2003 20:07:25 -0500


At 06:14 PM 3/11/03 -0500, Jeremy Hylton wrote:
>On Tue, 2003-03-11 at 17:43, Phillip J. Eby wrote:
> > At 04:35 PM 3/11/03 -0500, Jim Fulton wrote:
> > >The way you would reject base-class interfaces is to use implements. 
> That is,
> > >if you use implements, you implement *just* what you say you implement,
> > >so I still think 'doesNotImplement()' is a yagni.
> >
> > This is probably a matter of design principles.  In general, I go for the
> > Liskov substitutability principle; that is, I should be able to use a
> > subclass where the superclass is acceptable.  This implies, in other 
> words,
> > that failing to implement a superclass' interfaces is a no-no.
>
>I think substitutability is a goal here, but in a specialized way.  You
>should be able to substitute any implementation of the interface.  I
>think one of the purposes of interfaces is to decouple substitutability
>from inheritance.  If you want to class B to inherit from A but not be
>usable as an A, then you give it a different interface.

In essence, you're just repeating Jim's argument for why decla...  er, 
specifications should be explicit.  You're not actually answering my 
argument for why deviation from the LSP should be explicit.

IF one prefers to follow the LSP, THEN making deviation explicit is 
desirable.  I prefer to follow the LSP, as I understand it.

The whole purpose of inheritance, IMO, is to make it possible to understand 
and/or define a class *in terms of how it is different* from its 
base(s).  Requiring a restatement of its bases' interfaces in order to 
denote a change, is just as redundant as requiring one to restate the 
source code of the methods inherited from those bases!


> >   In the rare
> > case where I want to reject the legacy of my ancestors, I want to
> > explicitly identify what contracts I'm rejecting, rather than try to
> > reiterate every contract I might still implicitly be supporting.  I only
> > want to use 'implements()' if I want to reject *all* ancestral contracts,
> > which is something I've never wanted to do.  For that matter, because of
> > the LSP, I'm not sure I've ever actually rejected even one ancestral
> > contract, but I can easily conceive of situations where I might want to
> > reject some subset of them.
>
>If you are using inheritance just for implementation purposes and you
>don't want to claim to implement A's interfaces, then you should
>explicitly declare the interface(s) that B implements.  Otherwise, A may
>later evolve in implement interface IQuam.  When B was written, A didn't
>implement IQuam, so there was no need for B to say it did not implement
>IQuam.

But if A evolves to implement IQuam, then B may now implement IQuam as 
well, yes?  It seems to me at least as likely that you will want B to now 
implement IQuam; in fact, if you're inheriting from a framework-supplied 
base class, it's probably more likely that you'll want the interface to 
pass through.  (Unless, that is, you're misusing inheritance where 
delegation would be more appropriate - i.e., "using inheritance just for 
implementation purposes".)

I guess what I'm saying is, I personally would prefer to program in a style 
where only *changes* in the supplied interfaces are ever denoted in the 
class statements, because this is the way that makes it *hardest* to flout 
the LSP without visible consequences, thus highlighting potentially 
improper uses of inheritance.  That is, I would prefer to always use 
'alsoImplements()' and 'doesNotImplement()', and the latter should appear 
infrequently.

Or to put it even more briefly: "using inheritance just for implementation 
purposes" is evil.  :)  Sometimes it's a lesser evil, or an extremely 
tempting evil, but it is nonetheless an evil.  Inheritance is for "is-a" 
relationships, and "is-a" should normally imply inheritance of interface.

I could be wrong, but this may on some level be why so many people ask for 
inherited interface specs to be implicit, rather than explicit.