Абстрактные классы
Часть раздела Объектно-ориентированное программирование путешествия по 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()) и конструкторы. Подклассы наследуют их точно так же, как и при обычном наследовании. Ключевое отличие заключается в том, что вы не можете создать экземпляр самого абстрактного класса — вы должны использовать конкретный подкласс.
Задание
ЛегкоДавайте создадим систему транспортных средств, которая демонстрирует, как абстрактные классы служат чертежами для более конкретных типов. Вы создадите абстрактный базовый класс, который определяет общие черты всех транспортных средств, а затем расширите его конкретными типами транспорта.
Вы организуете свой код в двух файлах:
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и параметром hasSidecarfalse - Вызовите его метод
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() у мотоцикла
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыБиблиотеки и импортВведение в ООПКлассы и объектыКлючевое слово thisМетодыПеременные экземпляраОсновы конструкторовИтоги — Простой калькулятор4Null-безопасность
Введение в Null-безопасностьNullable и Non-Nullable типыОператоры ? и !Ключевое слово Late и Null-безопасностьNull-aware операторыNull-безопасность в классахИтоги — Система профилей пользователей7Абстрактные классы и интерфейсы
Абстрактные классыАбстрактные методыИнтерфейсы в DartНеявные интерфейсыРеализация против наследованияМножественные интерфейсыИтоги — Калькулятор фигур10Коллекции и обобщения
Обзор List, Set, MapТипобезопасные коллекцииОбобщенные классыОбобщенные методыОграничения обобщенийIterable и IteratorИтоги: Обобщенное хранилище13Продвинутые концепции ООП
Композиция против наследованияМетоды расширенияВызываемые классыЗапечатанные классы (Dart 3)Записи (Dart 3)Паттерны и сопоставление (3.0)Перечисления с методами16Проект: Управление библиотекой
Обзор проектаКлассы Book и User2Конструкторы в Dart
Конструктор по умолчаниюИменованные конструкторыСписки инициализацииКонстантные конструкторыФабричные конструкторыПеренаправляющие конструкторыИтоги — Shape Builder5Инкапсуляция
Публичные и приватные членыСоглашение о префиксе _Приватность на уровне библиотекГеттеры и сеттеры: подробный разборСкрытие данныхИтоги — Записи о студентах8Mixins
Введение в MixinsСоздание MixinsИспользование нескольких MixinsКлючевое слово on в MixinsMixin и наследованиеMixin и интерфейсИтоги: Система животных11Специальные методы
Переопределение toString()Переопределение hashCode и ==Интерфейс ComparableМетод call()Переопределение noSuchMethodПовторение — Пользовательская коллекция14Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy3Свойства классов
Члены экземпляра и статические членыПоля Final и ConstПеременные LateСтатические методы и поляГеттеры и сеттерыИтоги — Менеджер банковского счета6Наследование
Основы наследованияКлючевое слово superПереопределение методовАннотация @overrideКлючевое слово final для классовКонструкторы и наследованиеИтоги: Иерархия сотрудников9Полиморфизм
Основы полиморфизмаПолиморфизм через интерфейсыПроверка типов во время выполненияОператоры is и asКлючевое слово covariantИтоги — Обработчик платежей12Асинхронное ООП
Futures и async/awaitОсновы StreamsКонтроллеры StreamАсинхронные конструкторыАсинхронность в методах классовИтоги — Data Fetcher15Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий