Reputation: 44223
Perhaps first we should recall what the value of inheritance itself is. Inheritance is a mechanism for both code reuse and interface reuse (polymorphism). But you can have code reuse without inheritance by using composition and delegation. And in many languages you can have polymorphism without inheritance, but not all languages. In a strongly typed language such as C++, polymorphism, which is itself another important code reuse mechanism, can only be achieved using inheritance. In fact, C++ distinguishes between public and private inheritance for interface and code reuse respectively. More on this later.
Generally one thinks of a class's methods as creating a contract with clients of the class: It guarantees that as long as you call a method having met certain preconditions, the method will deliver certain results. "Proper" inheritance is such that the subclass instance can be substituted for its parent class without violating the parent's contract. That is, none of the subclass's methods should override its base class's methods requiring stricter preconditions nor delivering more "less" results. Returning to C++, since there is a clear distinction between public and private inheritance where the former is required so that you may substitute a subclass instance for a base class instance, it is generally considered "proper" that the substitution be semantically correct. Otherwise why not use private inheritance?
Is Ostrich
a valid subclass of Bird
? It depends on what your abstraction of Bird
is? If the Bird
class has a method Bird::fly
that does something tangible but Ostrich::fly
overrides this to throw an exception and thus delivers "less" than its base class, I would say no. But if class Bird
did not have a fly
method (there is another subclass Flying_Bird
that does), no problem.
My answer is that what holds for C++ is not a bad guideline for any object-oriented language. In a languages like Python where an inheritance hierarchy is not required for polymorphism, people might have a greater tendency to use inheritance just for code reuse. If this reuse is well-documented, it might not be an issue. But when I see a class hierarchy, my expectation is that a subclass is potentially going to be used polymorphically and thus an instance of the subclass can be substituted for an instance of the base class thereby obeyeing the Liskov substitution principle where a subclass is also a subtype.
Upvotes: 1
Reputation: 300029
I would like to add to what Justin and Baxter said.
The term proper inheritance is not really well-defined. Properly using inheritance is quite a subjective issue...
Consider the following example:
Bird
Ostrich
Should Ostrich
inherits from Bird
? From a zoological point of view it makes sense, but from a Computer Science point of view... not so much. If Bird
has a fly
method, then how am I supposed to handle this in Ostrich::fly
:x ?
There is somewhat of a war in the CS community. Indeed you'll regularly see books where Circle
inherits from Ellipse
(or the other way around) when it doesn't really makes sense from a CS point of view.
So my own little definition:
Considering that the interface defines precise semantics for each of its methods, a concrete class should only inherit from the interface if the implementation of each of the method matches the semantics specified.
Upvotes: 3
Reputation: 2456
When inheritance complies with a IS A relationship, as opposed to inheriting purely for code reuse without there being a logical subsumption of the child by the superclass.
Upvotes: 0
Reputation: 134227
This thread gives a nice summary:
Proper inheritance occurs when the derived class "IS A" specialized type of the base class. Example Cat IS A Animal.
Improper inheritance occurs when a class is inherited from merely for code reuse without having any other relationship. Example Cat Inherits from Engine. A Cat is not an engine however both an engine and a cat purr.
Upvotes: 4