Наследование и implements

Два механизма связи классов: наследование поведения и обязательство соответствовать интерфейсу.

extends наследует поля и методы родителя; implements обязывает класс соответствовать интерфейсу.

Наследование через extends

Дочерний класс получает поля и методы родителя и может их дополнять. Ключевое слово — extends:

class Animal {
  constructor(protected name: string) {}

  describe(): string {
    return "Это " + this.name;
  }
}

class Dog extends Animal {
  bark(): string {
    return this.name + " говорит: Гав!"; // name доступно — оно protected
  }
}

const d = new Dog("Рекс");
console.log(d.describe()); // "Это Рекс" — метод от родителя
console.log(d.bark());     // "Рекс говорит: Гав!" — свой метод

Здесь видно, зачем нужен protected: поле name скрыто снаружи, но доступно в наследнике Dog. Будь оно privatebark не смог бы его прочитать.

super и переопределение

Дочерний класс может переопределить метод родителя и при этом вызвать оригинал через super:

class Cat extends Animal {
  describe(): string {
    return super.describe() + " — это кот";
  }
}

console.log(new Cat("Барсик").describe()); // "Это Барсик — это кот"

Если у родителя конструктор с аргументами, в конструкторе наследника обязательно вызвать super(...) до обращения к this.

implements — контракт для класса

implements — другое: класс обязуется реализовать всё, что описано в интерфейсе. Интерфейс задаёт, что должен уметь класс, не диктуя как:

interface Shape {
  area(): number;
  perimeter(): number;
}

class Rectangle implements Shape {
  constructor(private w: number, private h: number) {}

  area(): number { return this.w * this.h; }
  perimeter(): number { return 2 * (this.w + this.h); }
}

Если забыть метод из интерфейса, компилятор сразу укажет на это:

class Circle implements Shape {
  constructor(private r: number) {}
  area(): number { return Math.PI * this.r ** 2; }
  // забыли perimeter()
}
// Ошибка: Class 'Circle' incorrectly implements interface 'Shape'. Property 'perimeter' is missing.

extends против implements

extendsimplements
наследует код (поля, методы)обязывает реализовать методы
только один родительможно несколько интерфейсов
«является разновидностью»«умеет делать»

Один класс может одновременно наследоваться и реализовывать интерфейсы: class Dog extends Animal implements Serializable. Несколько интерфейсов перечисляют через запятую — это удобный способ задать классу несколько контрактов сразу.

Зачем это: взаимозаменяемость

Благодаря implements разные классы с одним интерфейсом взаимозаменяемы. Функция, принимающая Shape, работает с любой фигурой — и с Rectangle, и с Circle. Это основа гибкого, расширяемого кода.

Итог

  • extends наследует реализацию родителя; protected-поля доступны наследникам, super зовёт родительский метод.
  • implements обязывает класс реализовать методы интерфейса — пропуск ловится компилятором.
  • Класс наследует один класс, но может реализовать несколько интерфейсов; это делает объекты взаимозаменяемыми.
Проверьте себя
1. Чем implements отличается от extends?
Aimplements наследует код родителя, extends — нет
Bextends наследует реализацию, implements лишь обязывает реализовать методы интерфейса
CМежду ними нет разницы
Dimplements можно применять только к функциям
2. Почему поле name в примере сделали protected, а не private?
Aprivate поля работают медленнее
BЧтобы оно было доступно в классах-наследниках (Dog, Cat)
Cprotected делает поле публичным
DЭто требование конструктора
3. Сколько интерфейсов может реализовать один класс через implements?
AТолько один
BНесколько, перечисленных через запятую
CРовно два
DНи одного, implements не поддерживает несколько
Поддержать проект