Favor Composition Over Inheritance

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 class B for its full lifetime. This is why we speak of a "Is a" relationship.

Naive example (just for the illustration):

Sample Image

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):

Sample Image

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 and cases,
  • 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



Leave a reply



Submit