DEV Community

Discussion on: Learn and use Composition in JavaScript and TypeScript

Collapse
 
jeffmottor profile image
Info Comment hidden by post author - thread only visible in this permalink
Jeff-Mott-OR

I'm sorry to say that you've been bamboozled. There's unfortunately misinformation circulating within the JavaScript community about object composition. That pattern you're showing here isn't object composition at all. In fact it's quite literally the opposite of composition. It's inheritance. It's multiple inheritance, to be more specific.

I'm going to show some examples in Python, because Python natively supports multiple inheritance. First up, just some basic single inheritance 101.

class Barker:
    def bark(self):
        print('Woof Woof!')

class Dog(Barker):
    pass # "pass" is the Python equivalent of an empty block {}

jack = Dog()
jack.bark() # Woof Woof!

The class Dog(Barker): part is Python syntax for inheritance. It may not spell out the word "extends", but you can recognize inheritance when you see it, right? In this example, "Dog" is the child class, and it inherits the properties and behavior of the parent, "Barker", which is why we can call "bark" on the child object.

But dogs need to eat too. Here's a slightly different example but still basic single inheritance 101.

class Eater:
    def eat(self):
        print(f'{self.name} is eating.')

class Dog(Eater):
    def __init__(self, name):
        self.name = name

jack = Dog('Jack')
jack.eat() # Jack is eating

In this example, "Dog" is the child class, and it inherits the properties and behavior of the parent, "Eater", which is why we can call "eat" on the child object. The only other difference here is the parent class, "Eater", uses an instance field, "name", that it expects the child class to provide. But otherwise this is still inheritance 101.

But dogs *both* bark and eat, don't they? We don't want to inherit just bark or inherit just eat. We want to inherit both. The feature to do that is called multiple inheritance, and in Python it's as easy as a comma.

class Barker:
    def bark(self):
        print('Woof Woof!')

class Eater:
    def eat(self):
        print(f'{self.name} is eating.')

class Dog(Barker, Eater):
    def __init__(self, name):
        self.name = name

jack = Dog('Jack')
jack.bark() # Woof Woof!
jack.eat() # Jack is eating

In this example, "Dog" is still the child class, and it inherits the properties and behavior of two parents, "Barker" and "Eater", which is why we can call both "bark" and "eat" on the child object.

But... this is starting to look eerily familiar, right? This is the kind of thing you've been doing with the spread operator, the kind of thing you've been misled into believing is object composition. It may not spell out the word "extends", but you can recognize inheritance when you see it, right?

Some comments have been hidden by the post's author - find out more