In my last post, I talked about instantiation patterns in JavaScript. This time, I'm going to go a little more in-depth on the ES6 pseudoclassical pattern, especially the process of creating child classes.
Child class?
Right, what exactly does that mean? Well, in JavaScript, a child class is a class that extends another class. Extends? Basically, a child class will have all the methods of its parent class available to it, as well as any methods that you specifically give the child class! This can be useful if you're going to create a bunch of similar objects that may have one or two slight differences. Lets take a look at an example. Just in case you forgot, we'll start with pseudoclassical instantiation using ES6 syntax.
// ES6 pseudoclassical instantiation
class Country {
constructor(continent, capital) {
this.continent = continent;
this.capital = capital;
}
whereAt() {
return `is located in ${this.continent}`;
}
capitalIs() {
return `has a capital of ${this.capital}`;
}
};
So lets assume that we're trying to make a bunch of objects that correspond to different countries around the world. They're all going to share SOME basic properties, right? In the code above, we're laying out the skeleton for each of our country objects. That is, every child of this Country class will at least have these methods available to them. Now lets look at how we make a child class:
// ES6 child class
class Italy extends Country {
constructor(country, continent, capital) {
super(continent, capital);
this.country = country;
}
colosseum() {
return 'Lions and tigers and bears, oh my!'
}
summary() {
return `The country of ${this.country} ${super.whereAt()} and ${super.capitalIs()}`;
}
};
const italy = new Italy('Italy', 'Europe', 'Rome');
italy.capital; // returns 'Rome'
italy.colosseum(); // returns 'Lions and tigers and bears, oh my!'
italy.summary(); // returns 'The country of Italy is located in Europe and has a capital of Rome'
So here we've made a child class, Italy, that has all the methods of its parent class, Country, available to it, as well as several new methods. But there's some stuff in there that we've never seen before, right? What's that "extends" keyword mean? What about that "super" method? Glad you asked!
Extends
The first thing you probably noticed is the word "extends". This just tells us that the class we're creating, Italy, is a child class of the class that follows it, Country. Again, this just means that all of the methods that were created in the Country class are available to the Italy class as well, without having to create or declare them again, which is a good example of making our code reusable.
Before we talk about super, lets go over the constructor method a bit. This a a special method that's used when objects are created and initialized in ES6 syntax. It basically allows you to assign properties to your object before you begin creating methods. Even if you don't create one, it will be called automatically for you, but it will be blank. In short, constructor is used to attach properties to your object.
Super
Back to our Italy example, you may notice that we invoke a second function in our constructor method, super(). When used this way, super calls the constructor method of the parent class, basically creating identical properties using the parameters of our child class. If you're reading closely you may notice that we use super a second, and even a third time in our code. In the summary method, we use super to call the methods of the parent object in the child object. Although this isn't extremely useful in our code, that doesn't mean that there aren't any uses for it!
You can also overwrite properties and methods passed in by the super method. Lets take a look at some more code:
// overwriting properties and methods
class Egypt extends Country {
constructor(country, continent, capital) {
super(continent, capital);
this.country = country;
this.continent = 'Its in Africa';
}
whereAt() {
return this.continent;
}
summary() {
return `The country of ${this.country} ${super.capitalIs()} and ${this.whereAt()}`;
}
};
const egypt = new Egypt('Egypt', 'Africa', 'Cairo');
egypt.continent; // returns 'Its in Africa';
egypt.summary(); // returns "The country of Egypt has a capital of Cairo and Its in Africa"
In the above code, you can see that we've overwritten the continent property of the parent class, as well as the whereAt method. Our Egypt object also has a slightly different summary method than our Italy object.
One final thing that might be worth remembering: if no parameters are passed to the constructor call or super call, it will generate the keys, but they will have values of undefined. As usual, I have an example for you:
// empty constructor functions
class Sweden extends Country {
constructor() {
super();
}
};
const sweden = new Sweden('Europe', 'Stockholm');
console.log(sweden); // returns Sweden {continent: undefined, capital: undefined}
In conclusion, extends and super allow you to easily create child classes from a parent class. Extends is used to denote the parent class that the child class will inherit its methods from, and super is used to reference the parent classes constructor method.
Top comments (1)
I'm curious to know in what practical context you would actually want to use this? I'm asking as a self-confessed cynic of the class paradigm in JS. The language provides far more elegant ways to share functionality between objects; so to me inheritance feels like something that's only ever going to be useful in very specific cases.
If you're coming from a 'classical' OOP background I'd recommend not limiting yourself with that way of thinking ;)