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.

https://us.pycon.org/2019/schedule/presentation/204/

PyCon 2019

May 04, 2019
Tweet

More Decks by PyCon 2019

Other Decks in Programming

Transcript

  1. The Perils of
    Inheritance
    Why We Should
    Prefer Composition

    View Slide

  2. Ariel Ortiz
    Full time faculty member
    Tecnológico de Monterrey
    Mexico

    View Slide

  3. bit.ly/2LpxtF1
    Slides available at:

    View Slide

  4. Inheritance
    is-a
    4
    base
    derived
    A base class is also known as a superclass. A derived class is also known as a
    subclass.

    View Slide

  5. Composition
    has-a
    5
    composite
    component
    A composite instance is composed by (wraps) a component instance.

    View Slide

  6. Examples

    View Slide

  7. OO Design Principle
    Favor object
    composition
    over class
    inheritance
    7

    View Slide

  8. white-box reuse
    class inheritance
    black-box reuse
    object composition
    In another time, copy/paste was the primary mechanisms of code reuse.

    View Slide

  9. ADVANTAGES OF
    INHERITANCE
    9

    View Slide

  10. 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.

    View Slide

  11. 2. Allows changing inherited
    implementation
    Advantage of Inheritance
    You can also add new behaviours in the derived classes.

    View Slide

  12. DISADVANTAGES OF
    INHERITANCE
    12

    View Slide

  13. 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.

    View Slide

  14. 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.

    View Slide

  15. 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

    View Slide

  16. 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.

    View Slide

  17. CODE EXAMPLE:
    LIFO LINKED LIST
    17
    Github link

    View Slide

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

    View Slide

  19. 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__()

    View Slide

  20. ADVANTAGES OF
    COMPOSITION
    20

    View Slide

  21. 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].

    View Slide

  22. 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.

    View Slide

  23. 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.

    View Slide

  24. 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].

    View Slide

  25. DISADVANTAGES OF
    COMPOSITION
    25

    View Slide

  26. 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 .

    View Slide

  27. 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.

    View Slide

  28. WHEN TO USE
    INHERITANCE
    28

    View Slide

  29. 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

    View Slide

  30. 2. When extending classes
    specifically designed and
    documented for extension
    When to use inheritance

    View Slide

  31. THINGS TO NOTE
    31

    View Slide

  32. 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.

    View Slide

  33. 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.

    View Slide

  34. 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.

    View Slide

  35. 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.

    View Slide

  36. 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”.

    View Slide

  37. 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.

    View Slide

  38. If it looks like a duck, quacks like a duck,
    but walks on wheels — You most likely have
    the wrong abstraction.
    38

    View Slide

  39. CONCLUSION
    39

    View Slide

  40. SHOULD WE USE INHERITANCE OR COMPOSITION?
    ¿POR QUÉ NO LOS DOS?

    View Slide

  41. View Slide

  42. Credits
    Special thanks to:
    ▪ Presentation template by SlidesCarnival
    ▪ Icons made by Freepik from Flaticon
    42

    View Slide