Наследование в JavaScript ES6
![Наследование в JavaScript ES6](/images/articles/js-inheritance-es6-classes-part-1.png)
В этой статье вы узнаете, как реализовать наследование в JavaScript, используя ключевые слова extends и super, появившиеся в ES6.
До появления ES6, для реализации наследования требовалось выполнить пару неочевидных шагов. Базовой методикой реализации являлось и является прототипное наследование. В примере ниже показано, как объект ABird наследует свойства от объекта SimpleAnimal посредством прототипного наследования.
function SimpleAnimal(legs) {
this.legs = legs;
}
SimpleAnimal.prototype.walk = function() {
console.log('ходит на ' + this.legs + ' конечностях');
}
function ABird(legs) {
SimpleAnimal.call(this, legs);
}
ABird.prototype = Object.create(SimpleAnimal.prototype);
ABird.prototype.constructor = SimpleAnimal;
ABird.prototype.fly = function() {
console.log('летает');
}
var pigeon = new ABird(2);
pigeon.walk(); // ходит на 2 конечностях
pigeon.fly(); // летает
В ES6 последовательность необходимых действий сведена к минимуму, так как для этого используются ключевые слова JavaScript extends и super. Следующий пример определяет классы SimpleAnimal и ABird.
class SimpleAnimal {
constructor(legs) {
this.legs = legs;
}
walk() {
console.log('ходит на ' + this.legs + ' конечностях');
}
}
class ABird extends SimpleAnimal {
constructor(legs) {
super(legs);
}
fly() {
console.log('flying');
}
}
let ABird = new ABird(2);
ABird.walk();
ABird.fly();
В этом примере в конструкторе класса ABird используется ключевое слово JavaScript super для вызова конструктора базового класса SimpleAnimal с указанными аргументами.
Учтите, что новая версия класса - это просто синтаксический сахар над методикой прототипного наследования в JavaScript. Другими словами, хоть JavaScript и использует новый синтаксис классов, но наследование все еще реализуется через механизм прототипов.
Класс SimpleAnimal называется базовым классом, а класс ABird - производным. В JavaScript требуется, чтобы производный класс использовал ключевое слово super, если он имеет конструктор. В примере выше, инструкция super(legs) эквивалентна следующей инструкции - SimpleAnimal.call(this, legs);
class ABird extends SimpleAnimal {
fly() {
console.log('flying');
}
}
Это будет эквивалентно следующему:
class ABird extends SimpleAnimal {
constructor(...args) {
super(...args);
}
fly() {
console.log('flying');
}
}
Однако, если вы используете конструктор в производном классе, то обязательно необходимо вызвать функцию super(), в противном случае создать объект производного класса не получится.
class ABird extends SimpleAnimal {
constructor(legs) {}
fly() {
console.log('летает');
}
}
let ABird = new ABird(2); // Ошибка!!!
Поскольку super() инициализирует объект базового класса, перед обращением к производному объекту, обязательно необходимо вызвать конструктор базового класса. Попытка получить доступ к производному объекту до вызова super() приводит к ошибке.
Новые свойства в производный класс добавляются после инициализации базового класса:
class ABird extends SimpleAnimal {
constructor(legs, color) {
super(legs);
this.color = color; // окраска птички
}
fly() {
console.log('летает');
}
getColor() {
console.log(this.color);
}
}
let pegion = new ABird(2, 'белый');
console.log(pegion.getColor());
Сокрытие методов
В производный класс вы можете добавить метод с тем же именем, что и метод в базовом классе. И при вызове этого метода производного класса, он будет затенять, скрывать метод в базовом классе.
Следующий класс Dog расширяет класс SimpleAnimal и переопределяет метод walk().
class Dog extends SimpleAnimal {
constructor() {
super(4);
}
walk() {
console.log(`идет гулять`);
}
}
let bingo = new Dog();
bingo.walk(); // идет гулять
Чтобы вызвать метод базового класса в производном классе, нужно использовать инструкцию super.{имя метода}():
class Dog extends SimpleAnimal {
constructor() {
super(4);
}
walk() {
super.walk();
console.log(`идет гулять`);
}
}
let bingo = new Dog();
bingo.walk();
// ходит на 4 конечностях
// идет гулять
На этом все, а в следующей статье мы рассмотрим наследование статических методов и разберемся с расширением встроенных в JavaScript типов.
-
-
Михаил Русаков
Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.