Using inheritance to utilize base class members even when there is no clear 'type of' relationship.
Why is this misusing inheritance? If access is needed to base class members, why not provide it?
Consider the following PseudoCode
class Bird { virtual fly() { flapWings(); } virtual feed { digForGrubs(); } } class Pig extends Bird { virtual feed { super.digForGrubs(); rootForTruffles(); } } Pig p = new Pig(); p.feed(); // okay p.fly(); // pigs fly?!!?You might consider this overly contrived, but I have seen cases in real code that were nearly as nonsensical.
I interpreted it as using trees when the change-pattern is not really tree-shaped, or classic "subtyping" is just not appropriate. (See links below.)
Isn't this merely bad class definition? I am not sure how this is anything that is peculiar to Inheritance.
This is using inheritance to get the superclass behavior when there is no clear type-of relationship. It really does happen that programmers who are unfamiliar with inheritance would not see this as a bad class definition because they see that Pig and Bird both feed and they need something on Bird. The inexperienced programmer may think in terms of type-of feeding (A Pig is a type-of thing that feeds by digging for grubs) and not see the larger picture that a Pig is not a subclass of Bird. Granted, this is extremely contrived, but there are real cases where a programmer has subclassed a totally inappropriate parent just to get some behavior. Perhaps refactoring, (class Grubfeeder?), composition, and delegation need to be stressed more in OO design. -- StevenNewton
java.util.Stack is a very good example of this. It inherits from Vector, because it "needs" certain implementation details from Vector. But a stack is not a vector at all, and this means you can randomly access elements of the stack.
It's really a language smell, because Java couples ImplementationInheritance and interface inheritance. You can have the latter without the former (through interfaces), but you can't have the former without the latter. SmallTalk has the same problem, but it's less evident because "private" is just a convention in SmallTalk. C++ gives you private inheritance, where you'd get digForGrubs() but wouldn't expose fly() or feed() to other classes. And the issue doesn't even come up in CommonLisp/Dylan/Cecil, because methods there don't belong to classes. -- JonathanTang
The example does not support the premise. The premise was "Using inheritance to utilize base class members ..." while the example concerned overriding base class methods. What is intended to be discussed here?
Oh my, I thought it was something most third-generation heirs were prone to do with Granddad's money ...
Oh, you mean investing it on www.petfood.com? :-)
Another example that I see more often:
class Animal { virtual bool feed() { chew(); swallow(); return true;} virtual bool fly() { flap(); return true; } virtual bool swim() { dive(); surface(); return true; } }; class Pig : public Animal { virtual bool fly() { return false;} // A pig is an animal that can't fly }; class Bird : public Animal { virtual bool swim() { return false; } // A bird is an animal that can't swim }; class Penguin : public Bird { // Shoot; in version 3.1 we have to support penguins?! virtual bool swim() { dive(); return true; } // Restore original behavior virtual bool fly() { return false; } // Current rev of penguin crashes when it flies // don't know why, so disable it };And then we wonder why our penguins keep drowning in the field. --TimLesher
See Also: ClassicOoAntiPatterns, LimitsOfHierarchies, ThereAreNoTypes, DeltaIsolation, LiskovSubstitutionPrinciple