Re: Inheritance of implementation: what is the reason of?



On Feb 18, 11:53 am, Robert Martin <uncle...@xxxxxxxxxxxxxxxx> wrote:
On 2008-02-17 14:23:14 -0600, Grizlyk <grizl...@xxxxxxxxx> said:

I am sure, if we can use composition, we must do it.

I wouldn't go that far.  There are cases where inheritance of
implementation is pretty useful.

class Subject {
  public:
    void Register(Observer* o) {
      observers.push_back(o);
    }

    void Notify() {
      for (iterator<Observer*> i=observers.begin();i!=observers.end(); i++)
        (*i)->Update();
    }

};

class SomeObservableClass : public Subject {
...

}

There's really no reason to prefer composition to inheritance in this case..

Actually there is. If we want to create a class that is substitutable
for Subject but doesn't implement Register or Notify in the exact same
way with the exact same fields, the above code would make that
difficult. No matter how you refactor it, you end up having to change
an indeterminate number of classes (either all of Subject's clients,
or all of Subjects current children.) That kind of shot-gun surgery,
breakage of the OCP is exactly what we are trying to avoid when
designing classes.

A well known rule is to have one thing do only one job, in the above
sample, Subject does two jobs, it defines the interface that all sub-
classes must conform to and defines an implementation that all sub-
classes must use. Granted these two jobs are not entirely orthogonal,
but in practice, they often diverge. Hence the "brittle base class
problem" (a problem common enough to warrant a name of its own.)

Dynamic typed languages avoid this problem because base classes do
*not* define the interface. In SmallTalk, for example, a class need
not derive from Subject for its objects to be used as Subject objects
are used.

It is a problem that users of static typed languages must live with.
Inheriting only for interface, while using composition for
implementation sharing (as Maksim suggests) makes for more complex
systems (in that there are more classes to deal with than there
otherwise would be,) but using inheritance for both interface and
implementation makes systems more rigid. Every individual situation
will be different. Designers using a static-typed languages must weigh
the trade-offs, then make a choice. Remember, if you can bat 300, your
a super-star! :-)

.



Relevant Pages

  • Re: How to generically look up the inheritance tree?
    ...     begin ... My current approach to things involves creating an interface for each ... a property and building lookup will behave ... property) and use the technique of passing things up the inheritance ...
    (comp.lang.pascal.delphi.misc)
  • Re: Visitor pattern, code generation and additional sub classes
    ... this is a base class / interface. ...     void visitFoo; ... in all my visitor implementations ... ...
    (comp.object)
  • Re: Entity and Identity
    ... has more to do with subtyping than inheritance. ... the best OO programmers prefer simple composition ...   A pure abstraction for a flushable output ... machines where assignment often becomes an implementation detail, ...
    (comp.databases.theory)
  • Re: best way to inherit funcs from another object
    ... document.write(script tag to include v4 lib js file) ...     func1: function, ... properties to multiple objects (which is effectively what prototype ... you haven't implemented prototype inheritance properly - it works ...
    (comp.lang.javascript)
  • Re: Multiple inheritance - How to call method_x in InheritedBaseB from method_x in InheritedBase
    ... I have a peculiar problem that involves multiple inheritance and method ...    class MyMixin: ... """ Enhanced container that can be moved in response to the user ... allows for optional layout settings specific to each child widget. ...
    (comp.lang.python)