Menu
Coddy logo textTech

Абстрактные классы

Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 43 из 110.

Абстрактный класс — это класс, экземпляр которого нельзя создать напрямую. Он служит шаблоном для других классов, определяя общую структуру, которой должны следовать подклассы. Вы создаете его с помощью ключевого слова abstract.

abstract class Shape {
  String color;
  
  Shape(this.color);
  
  void describe() {
    print('A $color shape');
  }
}

class Circle extends Shape {
  double radius;
  
  Circle(String color, this.radius) : super(color);
}

void main() {
  // Shape s = Shape('red');  // Ошибка! Нельзя создать экземпляр абстрактного класса
  var circle = Circle('blue', 5.0);
  circle.describe();  // Синяя фигура
}

Абстрактные классы полезны, когда у вас есть концепция, которая слишком общая, чтобы существовать сама по себе. «Shape» — это идея, но вы не можете нарисовать фигуру, не зная, является ли она кругом, прямоугольником или треугольником. Абстрактный класс определяет то, что является общим для всех фигур, в то время как конкретные подклассы предоставляют специфические детали.

Обратите внимание, что абстрактные классы все еще могут иметь обычные методы с реализацией (такие как describe()) и конструкторы. Подклассы наследуют их точно так же, как и при обычном наследовании. Ключевое отличие заключается в том, что вы не можете создать экземпляр самого абстрактного класса — вы должны использовать конкретный подкласс.

challenge icon

Задание

Легко

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

Вы организуете свой код в двух файлах:

  • vehicle.dart: Определите здесь иерархию транспортных средств:
    • Абстрактный класс abstract class Vehicle со свойствами String brand и int year. Включите конструктор, принимающий оба значения, и метод displayInfo(), который выводит [brand] ([year])
    • Класс Car, который расширяет Vehicle и добавляет свойство int doors. Включите метод honk(), который выводит Beep beep!
    • Класс Motorcycle, который расширяет Vehicle и добавляет свойство bool hasSidecar. Включите метод revEngine(), который выводит Vroom!
  • main.dart: Импортируйте файл с транспортными средствами и продемонстрируйте работу абстрактных классов:
    • Создайте Car с брендом 'Toyota', годом 2022 и количеством дверей 4
    • Вызовите его метод displayInfo() (унаследованный от Vehicle)
    • Выведите Doors: [doors]
    • Вызовите его метод honk()
    • Выведите пустую строку
    • Создайте Motorcycle с брендом 'Harley', годом 2021 и параметром hasSidecar false
    • Вызовите его метод displayInfo()
    • Выведите Has sidecar: [hasSidecar]
    • Вызовите его метод revEngine()

Помните, что вы не можете создать экземпляр Vehicle напрямую, так как он абстрактный — вы должны использовать один из конкретных подклассов. И Car, и Motorcycle наследуют метод displayInfo() от абстрактного родительского класса.

Ожидаемый вывод:

Toyota (2022)
Doors: 4
Beep beep!

Harley (2021)
Has sidecar: false
Vroom!

Шпаргалка

Абстрактный класс — это класс, экземпляр которого нельзя создать напрямую. Он служит шаблоном для других классов, определяя общую структуру, которой должны следовать подклассы. Создайте его с помощью ключевого слова abstract:

abstract class Shape {
  String color;
  
  Shape(this.color);
  
  void describe() {
    print('A $color shape');
  }
}

class Circle extends Shape {
  double radius;
  
  Circle(String color, this.radius) : super(color);
}

void main() {
  // Shape s = Shape('red');  // Ошибка! Нельзя создать экземпляр абстрактного класса
  var circle = Circle('blue', 5.0);
  circle.describe();  // A blue shape
}

Абстрактные классы могут иметь:

  • Обычные методы с реализацией
  • Конструкторы
  • Свойства

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

Попробуйте сами

import 'vehicle.dart';

void main() {
  // TODO: Создайте объект Car с маркой 'Toyota', годом 2022 и 4 дверями
  
  // TODO: Вызовите displayInfo() у автомобиля
  
  // TODO: Выведите "Doors: [doors]"
  
  // TODO: Вызовите honk() у автомобиля
  
  // TODO: Выведите пустую строку
  
  // TODO: Создайте объект Motorcycle с маркой 'Harley', годом 2021 и hasSidecar false
  
  // TODO: Вызовите displayInfo() у мотоцикла
  
  // TODO: Выведите "Has sidecar: [hasSidecar]"
  
  // TODO: Вызовите revEngine() у мотоцикла
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование