This post is based on the question https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance/11758048#comment15634305_11758048.
Some people said – check whether there is “is-a” relationship. If it is there use inheritance. What I think is there should be a second check for using inheritance. Use inheritance only if the base class is abstract. If the base class need to be instantiated then use composition; not inheritance.
E.g 1. Accountant is an Employee. But I will not use inheritance because a Employee object can be instantiated. (When you talk to business people, they will tell you – Accountant is an Employee. But in OO world Accountant is not (should not be) an employee)
E.g 2. Book is a SellingItem. A SellingItem cannot be instantiated – it is abstract concept. Hence I will use inheritance. The SellingItem is an abstract base class (or interface in C#)
What I am looking for here is an example that will challenge my argument –that is a scenario in which inheritance is better than composition even though the base class is non-abstract (base class can be instantiated). Can you please provide such an example?
Note: It would be more helpful if you can provide a scenario based on Bank domain, HR domain, Retail domain or any other popular domain.
Note: In the design, please assume that we have full control of the code. That is we are not using any external API. Also we are starting from beginning.
I will mark as answered if there is an example that explains a scenario that proves my argument is wrong. It is not a mere discussion on whether to use Composition or Inheritance.
I support @anon answer in https://stackoverflow.com/questions/3351666/why-use-inheritance-at-all?lq=1
The main reason for using inheritance is not as a form of composition – it is so you can get polymorphic behaviour. If you don’t need polymorphism, you probably should not be using inheritance.
@MatthieuM. says in Code Smell: Inheritance Abuse
The issue with inheritance is that it can be used for two orthogonal purposes:
interface (for polymorphism)
implementation (for code reuse)
REFERENCE
- Employee- Accountant Example https://stackoverflow.com/questions/11759120/issue-in-using-composition-for-is-a-relationship
- Selling Item Example – https://codereview.stackexchange.com/questions/14077/is-it-proper-tpt-inheritance
- Programming SOLID Principles
- Code Smell: Inheritance Abuse
8
Although you mentioned in a comment it’s not the talk about “composition vs inheritance”, I have to return to it. Because composition is better than inheritance If we assume that decoupling is always a good thing (Prefer composition to inheritance?).
Actually it is not always the case. Even if you see that “is a” can be replaced with “has a” or “has a” looks more promising, “is a” has a very nice automatic properties.
Consider any widget hierarchy. Usually everything related to dimension is buried deep at the root. And no matter how long the inheritance path, you can always directly call SetBounds
of the instance and pass the instance to a procedure that expects deep base object, the compiler will accept it because from “is a” comes automatic type conversion and access.
But if you convert the inheritance hierarchy into composition hierarchy (technically it is always possible), you will lose convenience in both cases, because you should point to the concrete piece of composition tree in order to change the dimension or provide a procedure with particular class type. Compare
MyForm.SetBounds(... // easy because of an "is a"-tree
MyForm.ScrollingWinControl.WinControl.Control.SetBounds //complex because of a "has a"-tree
or
GetSomeInfoOfControl(MyForm) // easy ...
GetSomeInfoOfControl(MyForm.ScrollingWinControl.WinControl.Control) //complex ...
So despite the price of stronger coupling, inheritance sometimes is much easy to manage and abstract.
2
The entire ‘is a’ vs ‘has a’ discussion never made any sense to me. There is already a good definition about when to use inheritance, so called “Liskov substitution principle”, which states:
Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.
The first thing you’ll notice is, that it is generally a bad idea to let people with PhD explain a simple problem.
Second, this exactly states when to use inheritance. If I may use Wikipedia’s article and apply it to your accountant/employee example:
Liskov’s notion of a behavioral subtype defines a notion of substitutability for mutable objects; that is, if
Accountant
is a subtype ofEmployee
, then objects of typeEmployee
in a program may be replaced with objects of typeAccountant
without altering any of the desirable properties of that program (e.g., correctness).
The entire Principles paragraph of the Wikipedia article contains some more interesting principles.
Apparently most answers refer to LSP in one way or the other. Baqueta cleverly disguised it as a easy-to-miss-link and Geek edited his post to include LSP seconds before I posted my answer. So, LSP seems to be the most reasonable way to create your hierarachy.
Some examples of where your principle doesn’t hold:
- bicycle and a mountain bike
- circle and a sphere
- A button and an image button or toggle button.
In WPF, the concrete System.Windows.Controls.Button has the following subclasses:
- CalendarButton
- CalendarDayButton
In Java and C#, everything extends directly or indirectly from object
, which isn’t abstract.
Also in WPF: DatePickerTextBox is a subclass of (the concrete) TextBox. There are lots more examples. These respect LSP and the base class is not abstract.
As an extra note. I think the reason you found this principle is because it is generally a good idea to keep your hierarchy very flat, because inheritance introduces coupling. One or two levels deep is more than enough. Abstract classes will (almost) always be subclassed somewhere, since that is the purpose of making a class abstract, so that others can make it specialized. Most concrete classes don’t need to be specialized in any way. That may be the reason you haven’t found an example yet.
0
I think you’ve actually got there is a good rule of thumb for choosing to make a class abstract: if there are (or you can forsee the need for) variants of a class with slightly different behaviour, then it’s often a good idea to create an abstract base class.
Bottom line though, in my experience: as long as the relationship you’re dealing with is really is-a (e.g. your Accountant-Employee example is more suited to composition than inheritance, as per this answer) then it’s very rarely harmful/problematic to inherit from non-abstract classes.
A couple of examples when you might want/have to ignore your rule. Both assume you require Poodle
to be substitutable for Dog
:
Dog
is a class in an external API and there’s noIDog
interface forPoodle
to implement.Dog
is already instantiated in dozens of different places in your (already tested) code.
Admittedly, these are both cases where a better original design might have helped, but in the real world designs are never perfect!
2
I think inheriting concrete class is OK and actually quite valuable feature.
The “is-a” rule is only good for extremely simple models and domains. The way I see it, is that classes represent behavior and encapsulate state where the state can be another class. What kind of behavior Accountant, Employee, Book and Selling item have in relation to our model? That is the question you should ask. And based on that use either inheritance of composition.
Also, many real-world object are not good examples, because they are usually composites of different behaviors, that can be shared between different real-world objects. Many animal species walk on all 4. That is good example of behavior.
Extending already existing behavior by inheritance is great way to simplify and modularise the model of the domain. And for our walk behavior example, we can extend WoundedWalk class, that does exactly what its name says.
0
I don’t think there is any necessity of a challenging example. What you say is a nice design principle which is named dependency inversion. That is, higher components should never depend on lower components. Lower components should depend on higher components only.
Like every rule, this one might have exceptions, too. But there are no rules without exceptions!
2
You use inheritance over composition when you need code reuse . Inheritance helps in evolving classes really fast . However , you should be careful not to overuse it . use it judiciously only when it makes sense (ie when you are absolutely sure that there is a “IS-A” relationship between every objects of both the classes .You need to make sure that the subclass objects respects the Liskov Substitution principle . Even then it might not be good idea everytime if you add a value component to a subclass and the super class also has the notion of a value component. From Effective Java :
There is no way to extend an instantiable class and add a value
component while preserving the equals contract, unless you are willing
to forgo the benefits of object-oriented abstraction.
On the other hand composition has multiple advantages over inheritance and so most of the times it is preferred over inheritance but that wasn’t your question. Spring’s *Dependency Injection principle * is primarily based on this premise .
0
What I am looking for here is an example that will challenge my argument
Examples abound:
-
Buttons. In many GUI frameworks, View is not an abstract class — you can and often do create vanilla views. But there are also plenty of subclasses of View, such as Button.
-
Mutable objects. Some frameworks, e.g. Cocoa, have data container classes that are immutable (NSArray, NSString, NSDictionary, etc.) and also mutable subclasses of those (NSMutableArray, NSMutableString, etc.). You can do anything to an instance of NSMutableArray that you can do to an instance of NSArray, and then some.
-
Employee. Borrowing from your Accountant example, its likely that an Employee class might be a subclass of Person, but there’s no reason that Person needs to be abstract.
-
Accountant. Your example is often given to illustrate how composition can/should be used in place of inheritance, but that doesn’t mean that composition is always the best choice in this case. Yes, you can create an accountant by separating the ‘job’ aspects from the ’employee’ and then configuring an instance of Employee with a particular job. But there may be good reasons to use inheritance instead. An accountant isn’t just an employee who happens to crunch numbers; an accountant is a particular kind of employee, and you may want to use inheritance to reflect that. For example, you might want the Accountant class to implement a ProfessionalStanding interface or to include functionality that helps detect conflicts of interest. Also, creating an Accountant class makes it possible to use the language’s type system to help prevent employees who aren’t accountants from being used in roles where only an accountant should be used:
Project::addAuditor(Accountant& a);
The decision to use or not use inheritance has little to do with whether a class is abstract. It’s the other way around, actually: abstract classes are used to force you to create a subclass, generally to ensure that important missing functionality is provided. The fact that you can instantiate a class certainly doesn’t mean that you should avoid subclassing.