Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ariel Ortiz - The Perils of Inheritance: Why We Should Prefer Composition

Ariel Ortiz - The Perils of Inheritance: Why We Should Prefer Composition

Inheritance is among the first concepts we learn when studying object-oriented programming. But inheritance comes with some unhappy strings attached. Inheritance, by its very nature, tends to bind a subclass to its superclass. This means that modifying the behavior of a superclass might alter the behavior of all its subclasses, sometimes in unanticipated ways. Furthermore, it’s commonly accepted that inheritance actually breaks encapsulation. So, if inheritance has these issues, what alternative do we have? More than two decades ago, The Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides) suggested in their famous Design Patterns book that we should favor object composition over class inheritance.

In this talk I will show some code examples in Python where inheritance goes astray and demonstrate how to correct them by using composition. My intention is not to demonize inheritance, but instead present how to use it wisely in order to improve the design of our object-oriented software so that it’s more flexible and easier to maintain.


PyCon 2019

May 04, 2019

More Decks by PyCon 2019

Other Decks in Programming


  1. Inheritance is-a 4 base derived A base class is also

    known as a superclass. A derived class is also known as a subclass.
  2. white-box reuse class inheritance black-box reuse object composition In another

    time, copy/paste was the primary mechanisms of code reuse.
  3. 1. Easy way to reuse code Advantage of Inheritance Inheritance

    is a concept built into Python. When defining a new class all you have to do is list the base classes to inherit their interface and implementation.
  4. 1. The relationship between a base class and a derived

    class is statically fixed Disadvantage of Inheritance In a class, once you have established what its bases classes are, you can’t dynamically change them.
  5. Disadvantage of Inheritance 2. Inheritance supports weak encapsulation and fragile

    structures Derived classes have privileged access to a base class’s implementation. This means that encapsulation is weak in inheritance relationships. Because of this, it’s possible that a change to a superclass implementation could break subclasses even if the public interface does not change.
  6. 3. A derived class inherits everything, even things it doesn’t

    need or want Disadvantage of Inheritance You wanted a banana but what you got was a gorilla holding the banana and the entire jungle. - Joe Armstrong
  7. Disadvantage of Inheritance 4. Changes in a base class interface

    impact all its derived classes If you change the signature of a base class method the change will ripple to all derived classes.
  8. LinkedList + __init__() + insert(value) + insert_all(iterable) + remove() +

    clear() + __iter__() + __str__() + __len__() InsertCounter + __init__() + insert(value) + insert_all(iterable) + counter()
  9. LinkedList + __init__() + insert(value) + insert_all(iterable) + remove() +

    clear() + __iter__() + __str__() + __len__() InsertCounter + __init__() + insert(value) + insert_all(iterable) + counter() + remove() + clear() + __iter__() + __str__() + __len__()
  10. 1. Implementations are configurable at runtime Advantage of Composition You

    can attach additional responsibilities to an object dynamically. This is the basis of the Decorator design pattern [GAMMA et al].
  11. 2. Supports good encapsulation and adaptable structures Advantage of Composition

    Composite classes that use composition are forced to go through the component class interface. That means that they enforce good encapsulation. That also means that changes in implementation of the component classes are less likely to break classes that use them. As long as the interface remains the same, the composite classes won’t break.
  12. 3. Interface changes have limited ripple effect Advantage of Composition

    When the interface of a component class changes, it will break the composite classes that rely on the old version of the interface. However, the damage is contained and generally fairly trivial to correct. Because interfaces are not inherited when using composition, the changes affect only the composite class, but not its clients.
  13. 4. Composition allows a composite class to have relationships with

    many component classes Advantage of Composition In this case, the composite class is effectively an implementation of the Façade design pattern [GAMMA et al].
  14. 1. Frequently requires more code than inheritance Disadvantage of Composition

    If a composite class needs to expose some or all of a component class’s interface, it must recreate it. This can be simplified by using in Python a package such as forwardable .
  15. 2. Often more difficult to read than inheritance Disadvantage of

    Composition Inheritance establishes a very straightforward relationship. Composition is often less direct and presents a trail that’s more difficult to follow if you’re not familiar with the code.
  16. 1. When the base and derived classes are in the

    same module/package and under the control of the same programmers When to use inheritance
  17. 1. Inheritance is not wrong Things to note Just because

    you should favor composition does not mean that inheritance is never appropriate. Inheritance is a better solution in some cases.
  18. 2. Only use inheritance when a new class really does

    define a subtype of an existing class Things to note You should only use inheritance if there is an “is-a” relationship between two classes.
  19. 3. Inheritance and composition are not competitors Things to note

    Although it is true that in almost all cases two classes will be related by either inheritance or composition (and not both), that does not mean that these two types of relationships can not work together. In fact, most classes that use inheritance also use composition.
  20. 4. Design and document for inheritance Example: JSONEncoder Things to

    note A class must clearly document any circumstances under which it might invoke an overridable method.
  21. 5. When using inheritance never forget the Liskov Substitution Principle

    (LSP) Things to note The LSP is one of the SOLID principles for object oriented design proposed by Robert Martin, a.k.a “Uncle Bob”.
  22. The Liskov Substitution Principle: functions that use references to base

    class objects must be able to use objects of derived classes without knowing it. 37 Formally, LSP is known as the subtype requirement, stated as: Let Φ(x) be a property provable about objects x of type T. Then Φ(y) should be true for objects y of type S where S is a subtype of T.
  23. If it looks like a duck, quacks like a duck,

    but walks on wheels — You most likely have the wrong abstraction. 38