When to Favor Inheritance Over Composition
Rather than change, maintainability, etc, I think the core concept matters. Does Is A relationship seem better than a Has A relationship in a given situation?
A recommended reading: Gang Of Four's discussion about Type, Interface, OOP, etc before they begin discussion about patterns.
Also take a look at:
Composition vs. Inheritance: How to Choose?
Favor composition over inheritance
When you use inheritance to reuse code from the superclass, rather than to override methods and define another polymorphic behavior, it's often an indication that you should use composition instead of inheritance.
The java.util.Properties
class is a good example of a bad use of inheritance. Rather than using a Hashtable to store its properties, it extends Hashtable, in order to reuse its methods and to avoid reimplementing some of them using delegation.
How to obey composition over inheritance and DRY principle at the same time here?
inheritance and protected variables should be avoided
Inheritance is fine, as long as you are not forcing users into using it when all they need an interface. Java's List<T>
and AbstractList<T>
provide a good example: if you need to use parts of shared implementation, inherit the abstract class; if you don't, implement the interface.
protected String name
field could be made private
, too, eliminating the use of protected variables.
Here is how the approach would work for your class hierarchy:
public interface Animal {
void setName(String name);
String getName();
void printInfo();
}
public abstract class AbstractAnimal implements Animal {
private String name;
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
abstract void printInfo();
}
public class Cat extends AbstractAnimal {
@Override
public void printInfo(){
System.out.println("I'm a cat");
}
}
public class Dog extends AbstractAnimal {
@Override
public void printInfo(){
System.out.println("I'm a dog");
}
}
Composition vs. Inheritance
Composition over inheritance
In OO design, a common advice is to prefer composition over inheritance. This might mislead to think that there is a relation between these two different concepts:
- Inheritance is about a relation between classes.
- Composition is a about relations between objects of classes.
Even more misleading: the "composition" used in the general OO literature corresponds in general to a simple UML association and is not to be understood as restrictive as the UML "composition".
Inheritance is about generalisation and specialisation
If class D
inherits from B
, it means that D
specialises a more general concept B
:
- It has all the properties and operations of
B
(without need to repeat them in the diagram), - It can have additional properties and operations that are not relevant for
B
, and - It can perform some operations of
B
differently. - Any object of class
D
is also an object of classB
for its full lifetime. This is why we speak of a "Is a" relationship.
Naive example (just for the illustration):
Composition is about association of objects of very different classes
If class B
"composes" (has a composition association with) C
, it means that the B
object can be associated with different C
objects over its lifetime. Anf that objects of class C
:
- always belong to a
B
object that owns it. This is why we sometimes speak of a "has a" relationship; - will not survive its owning
B
object .
Caution: UML composition is about an exclusive ownership. In the OO literature, the term "composition" often refers to weaker associations without any ownership or even exclusivity.
Naive example (just for the illustration):
What does composition mean in the composition vs inheritance debate?
In short
This is a terminological ambiguity. Almost all articles on the bridge pattern are directly inspired from the Gang of Four (GoF) who first defined this design pattern. And this is the cause of the ambiguity:
They used the term composition to mean object composition and not UML composition.
At the time they wrote their book, UML was not yet defined. Their graphical notation uses the hollow diamond with a different meaning than UML.
They were first to mention composition over inheritance, with the meaning of object composition as opposed to class inheritance.
More details
GoF's object composition is not UML composition
Object composition is the OOP technique that aims at making more complex objects by assembling simpler objects. It's defined on page 19 of the book:
Here, new functionality is obtained by assembling or composing objects to get more complex functionality. Object composition requires that the objects being composed have well-defined interfaces. This style of reuse is called black-box reuse, because no internal details of the objects are visible.
In UML this technique corresponds to the implementation of an association, a shared aggregation or an UML composition. But unlike UML composition, it does not imply exclusive ownership nor lifecycle management.
GoF graphical notation is not UML
The graphical notation of class diagram used in the book looks very much like UML. This is because it is based on OMT, a predecessor of UML. But there are slight differences in the use of symbols, as you can read on page 364 of GoF:
An object reference representing a part-of or aggregation relationship is indicated by an arrowheadded line with a diamond at its base.
In UML, a composition (black diamond) would match this definition. But UML-composition adds more requirement, such as an exclusive ownership and responsibility for the component's lifecycle. This is more restrictive than object composition and reference-based aggragation.
In UML a shared aggregation (hollow diamond) or even a simple association (no diamond) would also perfectly match this definition, keeping in mind that UML does not define the semantics of shared aggregation.
Composition over inheritance
GoF are as far as I know, the first who recommended composition over inheritance. Page 20 of their pioneering work they made the following very precise statement (highlighting by me):
Favor object composition over class inheritance
We all like short mantras. Hence, this was quickly taken over without "object" and "class".
Conclusion
Whenever people speak about GoF patterns, you'll face the risk that aggregation or composition symbols might not be accurate, and that composition could have several meanings. So, you need to read it with critical thinking and an open mind. As patterns are not magical recipes, and may anyway need to be adapted to your own constraints, this state of mind can only be of advantage for you ;-)
Both Inheritance and composition in Python, bad practice?
In short
Preferring composition over inheritance does not exclude inheritance, and does not automatically make the combination of both a bad practice. It's about making an informed decision.
More details
The recommendation to prefer composition over inheritance is a rule of thumb. It was first coined by GoF. If you'll read their full argumentation, you'll see that it's not about composition being good and inheritance bad; it's that composition is more flexible and therefore more suitable in many cases.
But you'll need to decide case by case. And indeed, if you consider some variant of the composite pattern, specialization of the leaf and composite classes can be perfectly justified in some situations:
- polymorphism could avoid a lot of
if
andcases
, - composition could in some circumstances require additional call-forwarding overhead that might not be necessary when it's really about type specialization.
- combination of composition and inheritance could be used to get the best of both worlds (caution: if applied carelessly, it could also give the worst of both worlds)
Note: If you'd provide a short overview of the context with an UML diagram, more arguments could be provided in your particular context. Meanwhile, this question on SE, could also be of interest
Related Topics
Maximum Size of a Method in Java 7 and 8
Mockito: Mock Private Field Initialization
Java Type Generic as Argument for Gson
What Does Maven Update Project Do in Eclipse
How to Give System Property to My Test via Gradle and -D
JPA Query.Getresultlist() - Use in a Generic Way
Getting Java.Lang.Reflect.Invocationtargetexception While Adding a Button to Layout
Java: Infinite Loop Using Scanner In.Hasnextint()
How to Convert a Java Object to Xml with Open Source APIs
What Code Does the Compiler Generate for Autoboxing
Drawing a Component to Bufferedimage Causes Display Corruption
How to Create a Delay in Swing
Random Number with Probabilities
Why Do I Need a Functional Interface to Work with Lambdas
In Java How to Re-Open System.In After Closing It
Java 8: How to Work with Exception Throwing Methods in Streams