Спадкування - це спосіб створити звʼязки «батько-дитина» між класами. Дочірній клас (який іноді називають підкласом) має доступ до поведінки та даних, визначених батьківським класом (який іноді називають надкласом).
class Pet {
constructor(name) {
this.name = name;
}
introduce() {
console.log(`This is my pet, ${this.name}.`);
}
}
class Dog extends Pet {}
const dog = new Dog('Otis');
dog.introduce();
// => This is my pet, Otis.
Ключове слово extends в оголошенні дочірнього класу встановлює звʼязок із батьківським класом через ланцюжок прототипів.
Обʼєкти, створені конструктором дочірнього класу, будуть мати прототип батьківського класу у своєму ланцюжку прототипів, що дає доступ до будь-яких методів або даних, визначених батьківським класом.
const dog = new Dog('Otis');
Dog.prototype.isPrototypeOf(dog); // => true
Pet.prototype.isPrototypeOf(dog); // => true
Pet.prototype.isPrototypeOf(Dog.prototype); // => true
Pet.prototype.hasOwnProperty('introduce'); // => true
Dog.prototype.hasOwnProperty('introduce'); // => false
dog.hasOwnProperty('introduce'); // => false
Якщо дочірній клас не визначає власної функції-конструктора, використовується конструктор батьківського класу.
Однак, якщо дочірній клас визначає власний конструктор, конструктор батьківського класу потрібно викликати явно.
Щоб викликати конструктор батьківського класу з області видимості конструктора дочірнього класу, використовують ключове слово super.
class Pet {
constructor(name) {
this.name = name;
}
}
class Dog extends Pet {
constructor(name, breed) {
super(name);
this.breed = breed;
}
}
const dog = new Dog('Otis', 'Pug');
Оскільки конструктор батьківського класу відповідає за ініціалізацію нового обʼєкта та присвоєння його this, його потрібно викликати до того, як конструктор дочірнього класу використає this.
class Dog extends Pet {
constructor(name, breed) {
// using 'this' before calling the parent constructor with 'super'
this.breed = breed;
super(name);
}
}
const dog = new Dog('Otis', 'Pug');
// => ReferenceError: Must call super constructor in derived class before accessing 'this'...
Дочірній клас може визначати власну поведінку на додачу до поведінки, успадкованої від батьківського класу.
Це одна з головних причин використовувати спадкування: мати спеціалізовані дочірні класи з власними унікальними даними й методами, які повʼязані між собою спільними методами та даними, наданими батьківським класом.
class Dog extends Pet {
constructor(name, breed) {
super(name);
this.breed = breed;
}
describe() {
console.log(`${this.name} is a ${this.breed}.`);
}
}
const dog = new Dog('Otis', 'Pug');
dog.introduce();
dog.describe();
// => 'This is my pet, Otis.'
// => 'Otis is a Pug.'
Дочірній клас також може перевизначити поведінку методу, визначеного батьківським класом, і замінити або розширити її поведінкою, визначеною дочірнім класом.
class Cat extends Pet {
// replacing parent class behavior
introduce() {
console.log(`This is my cat, ${this.name}.`);
}
}
class Dog extends Pet {
constructor(name, breed) {
super(name);
this.breed = breed;
}
describe() {
console.log(`${this.name} is a ${this.breed}.`);
}
// extending parent class behavior
introduce() {
super.introduce();
this.describe();
}
}
const cat = new Cat('Milo');
cat.introduce();
// => 'This is my cat, Milo.'
const dog = new Dog('Otis', 'Pug');
dog.introduce();
// => This is my pet, Otis.
// => Otis is a Pug.
Щоб викликати метод, визначений у батьківському класі, з тіла однойменного методу дочірнього класу, потрібно використати ключове слово super, щоб звернутися до батьківського класу.