Как наследуются от класса в TypeScript?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Наследование в TypeScript
Наследование классов в TypeScript — это механизм объектно-ориентированного программирования, позволяющий создавать новый класс на основе существующего, перенимая его свойства и методы, а также расширяя или модифицируя его функциональность.
Базовый синтаксис наследования
Для наследования используется ключевое слово extends. Дочерний класс (наследник) получает доступ ко всем публичным (public) и защищенным (protected) членам родительского класса.
// Базовый класс (родительский)
class Animal {
constructor(public name: string) {}
move(distance: number = 0): void {
console.log(`${this.name} переместился на ${distance} метров`);
}
protected breathe(): void {
console.log(`${this.name} дышит`);
}
}
// Дочерний класс (наследник)
class Dog extends Animal {
private breed: string;
constructor(name: string, breed: string) {
super(name); // Вызов конструктора родительского класса
this.breed = breed;
}
bark(): void {
console.log(`${this.name} породы ${this.breed} лает: Гав!`);
this.breathe(); // Доступ к protected методу
}
// Переопределение метода
move(distance: number = 5): void {
console.log(`${this.name} бежит`);
super.move(distance); // Вызов родительского метода
}
}
// Использование
const myDog = new Dog('Бобик', 'Овчарка');
myDog.move(10); // Бобик бежит \n Бобик переместился на 10 метров
myDog.bark(); // Бобик породы Овчарка лает: Гав! \n Бобик дышит
Ключевые аспекты наследования
1. Конструктор и super()
- Конструктор дочернего класса обязан вызывать
super()до первого обращения кthis superпозволяет обращаться к родительскому классу
class Vehicle {
constructor(protected maxSpeed: number) {}
}
class Car extends Vehicle {
constructor(maxSpeed: number, public brand: string) {
super(maxSpeed); // Обязательный вызов
// Теперь можно использовать this
this.brand = brand;
}
}
2. Модификаторы доступа
public— доступны везде (по умолчанию)protected— доступны в классе и наследникахprivate— доступны только в классе-владельцеreadonly— только для чтения
class Base {
public publicProp = 'public';
protected protectedProp = 'protected';
private privateProp = 'private';
readonly constantProp = 'constant';
}
class Derived extends Base {
accessCheck() {
console.log(this.publicProp); // ✓ Доступно
console.log(this.protectedProp); // ✓ Доступно
// console.log(this.privateProp); // ✗ Ошибка: private
console.log(this.constantProp); // ✓ Доступно, но не для записи
}
}
3. Переопределение методов (Override)
Дочерний класс может переопределять методы родителя, сохраняя или изменяя логику:
class Shape {
getArea(): number {
return 0;
}
getDescription(): string {
return 'Фигура';
}
}
class Circle extends Shape {
constructor(private radius: number) {
super();
}
// Полное переопределение
getArea(): number {
return Math.PI * this.radius ** 2;
}
// Расширение родительского метода
getDescription(): string {
return `${super.getDescription()}: Круг радиусом ${this.radius}`;
}
}
Продвинутые возможности
1. Абстрактные классы
TypeScript поддерживает абстрактные классы, которые нельзя инстанциировать напрямую:
abstract class Database {
abstract connect(): Promise<void>;
protected log(message: string): void {
console.log(`[DB]: ${message}`);
}
}
class PostgreSQL extends Database {
async connect(): Promise<void> {
this.log('Подключаемся к PostgreSQL...');
// Реализация подключения
}
}
// const db = new Database(); // ✗ Ошибка: нельзя создать экземпляр абстрактного класса
const pg = new PostgreSQL(); // ✓ Можно
2. Наследование интерфейсов и реализация
TypeScript поддерживает множественное наследование через интерфейсы:
interface Swimmable {
swim(): void;
}
interface Flyable {
fly(): void;
}
class Bird {
move() {
console.log('Перемещается');
}
}
class Duck extends Bird implements Swimmable, Flyable {
swim(): void {
console.log('Плавает');
}
fly(): void {
console.log('Летает');
}
}
3. Статические члены и наследование
Статические свойства и методы также наследуются:
class Counter {
static totalCount: number = 0;
static incrementTotal(): void {
Counter.totalCount++;
}
}
class SpecialCounter extends Counter {
static specialIncrement(): void {
// Обращение к статическому свойству родителя
Counter.totalCount += 10;
}
}
Counter.incrementTotal();
SpecialCounter.specialIncrement();
console.log(Counter.totalCount); // 11
Практические рекомендации
- Используйте композицию вместо наследования, где это уместно
- Соблюдайте принцип подстановки Барбары Лисков — наследники должны быть взаимозаменяемы с родителями
- Избегайте глубоких иерархий наследования (более 2-3 уровней)
- Применяйте абстрактные классы для определения общего контракта
- Используйте
protectedвместоprivate, если планируется расширение класса
Ограничения TypeScript
- Нет множественного наследования классов (только через интерфейсы)
- Модификатор
privateне обеспечивает приватности во время выполнения (только на этапе компиляции) - Для истинной инкапсуляции используйте замыкания или новые поля класса с
#
Наследование в TypeScript предоставляет мощный инструмент для создания иерархий классов, повторного использования кода и построения сложных объектных моделей, сочетая при этом строгую типизацию и современные возможности ООП.