Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
Design patterns are the basis of any good software. JavaScript programs are no exception.
In this article, we’ll look at the difference between composition and inheritance, and look at why we should make our program have some flexibility.
Composition Versus Inheritance
Composition is when our object contains other objects.
Inheritance is when we receive the parent object’s members in the current object.
They both have their place.
Composition is a has-a relationship while inheritance is a has-a relationship.
It’s very important to make distinctions between the 2 since they do different things.
In JavaScript, there’re various ways that 2 things are composed.
For instance, we can have functions that are nested in other functions.
We can write:
const foo = fn => {
//...
fn();
//...
}
We have a foo
function that calls fn
.
Also, we can have nested objects. For example, we can write:
const obj = {
foo: 1,
bar: {
baz: 2,
}
}
We have an object as the value of bar
.
We can also have functions as values of object properties.
Composition is used for holding functionality that’s needed by something.
Inheritance, on the other hand, is an is-a relationship.
This means a child object is also a parent object. It’s just that a child object may have additional things.
For instance, if we have:
class Animal {
//...
}
class Cat extends Animal {
//...
}
Then Cat
is a subclass of Animal
. Cat
is an animal.
Cat
shares all the members of Animal
.
We can any methods ofAnimal
and access any instance variables of Animal
from a Cat
instance.
For example, we can write:
class Animal {
speak() {
//...
}
}
class Cat extends Animal {
//...
}
The extends
keyword indicates that Cat
inherits the members of Animal
.
Then if we create a Cat
instance, we can write:
const cat = new Cat();
Then we can call speak
by calling:
cat.speak();
Likewise, we can create an is-a relationship between 2 objects with the Object.create
method:
const animal = {
speak() {
//...
}
}
const cat = Object.create(animal);
Object.create
takes a prototype object which will be the prototype of the child object.
So animal
is the parent of cat
in the example above.
Like with class instances, we can call speak
by writing cat.speak()
.
In both the class and object examples, the prototype of the object resides in the __proto__
property of the object.
Inheritance is good for creating multiple classes or objects that share things from the parent class or object respectively.
The general principle is that if we have volatile code, then we should use more has-a relationships rather than an is-a relationship since we assume that shared code between a parent and different children may change.
If we change shared code between parents and children, then we break all the children as well.
Creating Algorithms
Once we decided on the patterns to use, then we’ve to devise our algorithm for our program.
This should be easy once we created some basic designs. Implementation is all that’s needed in most cases.
We can use existing libraries to make our lives easier, which is what we should do in most cases.
If we have an is-a relationship between classes or objects, then we need to think about which pieces of code are shared and which ones are unique to classes or objects.
If we use a has-a model instead, then we can create algorithms in different places and use them as we wish to.
We should think about making our program configurable so that we don’t have to change code to have slightly different functionality.
This way, we make our lives easier since code change always has some risks.
To reduce that, we should make things that change frequently be configurable so that we don’t have to deal with them.
For instance, we can read settings from a file or database so an algorithm can be selected according to settings that are set in those places.
Conclusion
Our programs should have some flexibility so that we don’t have to change code for it to do different things.
Composition is when we have something in an object or class so we can use them as we wish.
Inheritance is when we have some shared code that’s used by other objects or classes.