Unintended inheritance

K

Kay Schluehr

The problem of unintended inheritance is typical for OO frameworks and
can be explained as follows. Given a class Foo implemented by Alice and
a derived class Bar of Foo implemented by Bob. Bar implements a method
f. In a later version of Foo Alice also implements a method f. The f of
Bar overrides the f of Foo unintentionally. If an instance bar of Bar
will be created and some method g of Foo calls f it is the wrong f,
namely the one of bar will be called.

To prevent unintended inheritance C# introduced a relatively complex
contract semantics using three modifiers virtual, override and new. Is
this issue serious for Python programmers, in particular for those
working in larger projects ( Twisted, Zope ... ) or is it not? If not,
why not?

Kay
 
A

Alex Martelli

Kay Schluehr said:
To prevent unintended inheritance C# introduced a relatively complex
contract semantics using three modifiers virtual, override and new. Is
this issue serious for Python programmers, in particular for those
working in larger projects ( Twisted, Zope ... ) or is it not? If not,
why not?

I have not found it to be a particular problem (in C++ as well as in
Python or Java), because subclasses' coupling to superclasses is too
strong anyway to expect everything to just work smoothly when the
superclass's interface is changed, and even the most semidecent of
unittests easily catch this specific problem -- obviously all subclasses
must be recompiled and tested when a superclass's interface is changed
in any way. Other kinds of coupling are subtler and more problematic
(not so much in Python as in C++, I'd say, but it's arguable).

Lakos' book on large-scale design for C++ has good advice on dependency
control, which boils down to (WAY oversimplifying): each component must
expose to all others only unchanging abstract interfaces; anything
depending on anything beyond an abstract interface (as a subclass must)
must be in the same component as what it depends on. Inheritance, while
way handy, introduces too-strong coupling (==dependencies) to be freely
used across independently developed and maintained components; and any
change in interface (I would argue, in fact, most any change in
PROTOCOL, which is a stronger constraint) must occur on new, separate
interfaces (which may well extend the existing ones, of course).

Yes, frameworks (separately developed, large components which are
*supposed* to be used via inheritance by separately developed and
maintained components) are quite problematic in terms of Lakos' rules
and guidelines (if you're at all interested in these subjects you should
surely read Lakos' book, anyway: no summary can do it justice). But I
believe (with no real-world experience of C#, admittedly) that they will
remain essentially just as problematic with C#'s complex rules -- a new
release of a framework, which changes protocols, will still be able to
break uncountable independently developed and maintained smaller
components, and the fact that the compiler catches the breakage (if, of
course, the other components DO get recompiled) rather than relying on
semidecent unittests is scant consolation -- there's still no bound to
the amount of work that may be needed to repair the wreckage.


Alex
 
K

Kay Schluehr

Alex said:
I have not found it to be a particular problem (in C++ as well as in
Python or Java), because subclasses' coupling to superclasses is too
strong anyway to expect everything to just work smoothly when the
superclass's interface is changed, and even the most semidecent of
unittests easily catch this specific problem -- obviously all subclasses
must be recompiled and tested when a superclass's interface is changed
in any way. Other kinds of coupling are subtler and more problematic
(not so much in Python as in C++, I'd say, but it's arguable).

Lakos' book on large-scale design for C++ has good advice on dependency
control, which boils down to (WAY oversimplifying): each component must
expose to all others only unchanging abstract interfaces; anything
depending on anything beyond an abstract interface (as a subclass must)
must be in the same component as what it depends on. Inheritance, while
way handy, introduces too-strong coupling (==dependencies) to be freely
used across independently developed and maintained components; and any
change in interface (I would argue, in fact, most any change in
PROTOCOL, which is a stronger constraint) must occur on new, separate
interfaces (which may well extend the existing ones, of course).

Yes, frameworks (separately developed, large components which are
*supposed* to be used via inheritance by separately developed and
maintained components) are quite problematic in terms of Lakos' rules
and guidelines (if you're at all interested in these subjects you should
surely read Lakos' book, anyway: no summary can do it justice). But I
believe (with no real-world experience of C#, admittedly) that they will
remain essentially just as problematic with C#'s complex rules -- a new
release of a framework, which changes protocols, will still be able to
break uncountable independently developed and maintained smaller
components, and the fact that the compiler catches the breakage (if, of
course, the other components DO get recompiled) rather than relying on
semidecent unittests is scant consolation -- there's still no bound to
the amount of work that may be needed to repair the wreckage.


Alex

Interesting statement, Alex, as always. I've found an interview with
Anders Hejlsberg from 2003 on Artima where he defended his C# design
decisions with regard to the problem of "unintended inheritance":

http://www.artima.com/intv/nonvirtual.html

A strange twist is Anders exemplification of "pragmatism" with which
Bruce Eckel seems to agree emphatically. I would indeed assume the
exact opposite: laisser faire by pragmatists and expressive control by
academics. I'm also not sure what I should think about the confusing
use of the word "versioning" that is placed concretely by Bruce Eckel (
"DLL hell" ) but more metaphorically by Anders. His remarks about the
difference of ingoing and outgoing interfaces are interesting but
remain a little underdeveloped.

Kay
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top