TypeScript - Наследование

Здравствуйте, будущие программисты! Сегодня мы отправимся в увлекательное путешествие в мир наследования в TypeScript. Как ваш добрый сосед-преподаватель информатики, я здесь, чтобы помочь вам освоить эту fascинирующую тему. Так что возьмите свои виртуальные рюкзаки и погружайтесь с мной!

TypeScript - Inheritance

Что такое наследование?

Прежде чем мы начнем, давайте поймем, что такое наследование на самом деле. Представьте, что вы создаете генеалогическое древо. Each новое поколение наследует определенные черты от своих родителей. В программировании наследование работает аналогично. Оно позволяет новой классу быть основанным на существующем классе, наследуя его свойства и методы. Круто, правда?

đơn nhất наследование

Давайте начнем с simplest формы наследования: đơn nhất наследование. Это когда один класс (дочерний класс) наследуется от другого класса (родительского класса).

Основной пример

class Animal {
name: string;

constructor(name: string) {
this.name = name;
}

makeSound(): void {
console.log("Some generic animal sound");
}
}

class Dog extends Animal {
breed: string;

constructor(name: string, breed: string) {
super(name);
this.breed = breed;
}

makeSound(): void {
console.log("Woof! Woof!");
}
}

let myDog = new Dog("Buddy", "Golden Retriever");
console.log(myDog.name);  // Output: Buddy
console.log(myDog.breed); // Output: Golden Retriever
myDog.makeSound();        // Output: Woof! Woof!

В этом примере, Dog наследуется от Animal. Ключевое слово extends используется для создания класса, который является ребенком другого класса.

Объяснение

  1. Мы определяем базовый класс Animal с свойством name и методом makeSound.
  2. Затем мы создаем класс Dog, который наследуется от Animal.
  3. Класс Dog имеет свое собственное свойство breed.
  4. Мы используем ключевое слово super в конструкторе Dog для вызова конструктора Animal.
  5. Мы переопределяем метод makeSound в классе Dog.

Ключевое слово Super

Вы, возможно, заметили ключевое слово super в нашем предыдущем примере. Давайте углубимся в то, что оно делает.

Пример с Super

class Vehicle {
make: string;
model: string;

constructor(make: string, model: string) {
this.make = make;
this.model = model;
}

getInfo(): string {
return `${this.make} ${this.model}`;
}
}

class Car extends Vehicle {
numDoors: number;

constructor(make: string, model: string, numDoors: number) {
super(make, model);
this.numDoors = numDoors;
}

getInfo(): string {
return `${super.getInfo()} with ${this.numDoors} doors`;
}
}

let myCar = new Car("Toyota", "Corolla", 4);
console.log(myCar.getInfo()); // Output: Toyota Corolla with 4 doors

Объяснение

  1. Ключевое слово super используется в конструкторе Car для вызова конструктора Vehicle.
  2. В методе getInfo класса Car мы используем super.getInfo() для вызова метода getInfo родительского класса.

Ключевое слово super позволяет нам доступа к функциям и методам родителя объекта.

Переопределение метода

Переопределение метода occurs когда дочерний класс предоставляет конкретную реализацию метода, уже определенного в его родительском классе. Мы на самом деле видели это в обоих наших предыдущих примерах!

Другой пример переопределения метода

class Shape {
getArea(): number {
return 0;
}
}

class Circle extends Shape {
radius: number;

constructor(radius: number) {
super();
this.radius = radius;
}

getArea(): number {
return Math.PI * this.radius * this.radius;
}
}

class Rectangle extends Shape {
width: number;
height: number;

constructor(width: number, height: number) {
super();
this.width = width;
this.height = height;
}

getArea(): number {
return this.width * this.height;
}
}

let myCircle = new Circle(5);
console.log(myCircle.getArea()); // Output: 78.53981633974483

let myRectangle = new Rectangle(4, 5);
console.log(myRectangle.getArea()); // Output: 20

Объяснение

  1. У нас есть базовый класс Shape с методом getArea, который возвращает 0.
  2. Классы Circle и Rectangle наследуются от Shape и переопределяют метод getArea своими own реализациями.
  3. Класс Circle вычисляет площадь по формуле πr².
  4. Класс Rectangle вычисляет площадь, умножая ширину на высоту.

Многоуровневое наследование

Многоуровневое наследование involves дочерний класс, наследующийся от другого дочернего класса. Это как генеалогическое древо с несколькими поколениями.

Пример многоуровневого наследования

class Grandparent {
surname: string;

constructor(surname: string) {
this.surname = surname;
}

getSurname(): string {
return this.surname;
}
}

class Parent extends Grandparent {
firstName: string;

constructor(firstName: string, surname: string) {
super(surname);
this.firstName = firstName;
}

getFullName(): string {
return `${this.firstName} ${this.getSurname()}`;
}
}

class Child extends Parent {
middleName: string;

constructor(firstName: string, middleName: string, surname: string) {
super(firstName, surname);
this.middleName = middleName;
}

getFullName(): string {
return `${this.firstName} ${this.middleName} ${this.getSurname()}`;
}
}

let myChild = new Child("John", "Doe", "Smith");
console.log(myChild.getFullName()); // Output: John Doe Smith

Объяснение

  1. У нас есть класс Grandparent с property surname.
  2. Класс Parent наследуется от Grandparent и добавляет property firstName.
  3. Класс Child наследуется от Parent и добавляет property middleName.
  4. Каждый класс имеет own реализацию метода getFullName.

Резюме методов наследования

Вот таблица, резюмирующая ключевые методы и ключевые слова, которые мы обсуждали:

Метод/Ключевое слово Описание
extends Используется для создания класса как ребенка другого класса
super() Вызывает конструктор родительского класса
super.method() Вызывает метод из родительского класса
Переопределение метода Предоставление новой реализации метода в дочернем классе

И вот и все! Мы рассмотрели основы наследования в TypeScript. Помните, что практика делает perfect, так что не стесняйтесь экспериментировать с этими концепциями. Удачи в кодировании, будущие маги TypeScript!

Credits: Image by storyset