← Назад к вопросам

Зачем нужны Abstract Class?

1.8 Middle🔥 171 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Abstract Class (Абстрактные классы)

Абстрактные классы - это специальные классы в объектно-ориентированном программировании, которые определяют интерфейс и общую логику для наследующих их классов, но не могут быть инстанцированы напрямую.

Что такое абстрактный класс?

Абстрактный класс - это класс, содержащий абстрактные методы (без реализации) и конкретные методы (с реализацией). Он служит шаблоном для подклассов.

Зачем нужны абстрактные классы?

1. Определение контракта (интерфейс)

Абстрактный класс задаёт, какие методы должны быть реализованы в подклассах:

class Animal {
  // Абстрактный метод - должен быть переопределён
  makeSound() {
    throw new Error("Method 'makeSound' must be implemented");
  }

  // Конкретный метод - общая логика
  sleep() {
    console.log("Zzz...");
  }
}

class Dog extends Animal {
  makeSound() {
    console.log("Woof!");
  }
}

const dog = new Dog();
dog.makeSound(); // Woof!
dog.sleep();     // Zzz...

2. Переиспользование кода

Общая логика находится в абстрактном классе, подклассы наследуют её:

class DataProcessor {
  process(data) {
    const cleaned = this.clean(data);
    const validated = this.validate(cleaned);
    return this.transform(validated);
  }

  clean(data) {
    throw new Error("Must implement clean()");
  }

  validate(data) {
    throw new Error("Must implement validate()");
  }

  transform(data) {
    throw new Error("Must implement transform()");
  }
}

class JSONProcessor extends DataProcessor {
  clean(data) {
    return data.trim();
  }

  validate(data) {
    return JSON.parse(data); // Выбросит ошибку если невалидный JSON
  }

  transform(data) {
    return data.map(item => ({
      ...item,
      timestamp: new Date()
    }));
  }
}

3. Полиморфизм

Различные реализации одного интерфейса:

class Shape {
  getArea() {
    throw new Error("Must implement getArea()");
  }
}

class Circle extends Shape {
  constructor(radius) {
    super();
    this.radius = radius;
  }

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

class Rectangle extends Shape {
  constructor(width, height) {
    super();
    this.width = width;
    this.height = height;
  }

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

const shapes = [new Circle(5), new Rectangle(4, 6)];
shapes.forEach(shape => console.log(shape.getArea()));

4. Предотвращение ошибок

Знание о требуемых методах помогает не забыть реализовать что-то важное:

class Repository {
  create(data) {
    throw new Error("Must implement create()");
  }

  read(id) {
    throw new Error("Must implement read()");
  }

  update(id, data) {
    throw new Error("Must implement update()");
  }

  delete(id) {
    throw new Error("Must implement delete()");
  }
}

// Разработчик видит ВСЕ методы, которые нужно реализовать
class UserRepository extends Repository {
  create(user) { /* */ }
  read(id) { /* */ }
  update(id, user) { /* */ }
  delete(id) { /* */ }
}

Отличие от интерфейсов

Абстрактный класс:

  • Может содержать конкретные методы с реализацией
  • Может иметь свойства с начальными значениями
  • Может иметь приватные члены
  • Один класс может наследовать только один абстрактный класс

Интерфейс:

  • Только сигнатуры методов (в TypeScript)
  • Нет реализации
  • Один класс может реализовывать несколько интерфейсов

В TypeScript (более явно)

abstract class Vehicle {
  abstract start(): void;
  
  drive() {
    this.start();
    console.log("Driving...");
  }
}

class Car extends Vehicle {
  start(): void {
    console.log("Engine started");
  }
}

// const v = new Vehicle(); // Ошибка: Cannot instantiate abstract class
const car = new Car();
car.drive(); // Engine started, Driving...

Когда использовать?

  • Создание иерархии классов с общей логикой
  • Определение контракта для подклассов
  • Реализация паттерна Template Method
  • Полиморфное поведение в приложении

Абстрактные классы - мощный инструмент для создания масштабируемого и поддерживаемого кода с чётко определённой архитектурой.