Ключевое слово on в Mixins
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 53 из 110.
Иногда примеси необходимо использовать методы или свойства класса, в который она включена. Ключевое слово on позволяет ограничить использование примеси только теми классами, которые расширяют определенный тип.
class Animal {
String name;
Animal(this.name);
void breathe() => print('$name is breathing');
}
mixin Swimming on Animal {
void swim() {
print('$name is swimming'); // Можно получить доступ к 'name' из Animal
breathe(); // Можно вызывать методы Animal
}
}
class Fish extends Animal with Swimming {
Fish(String name) : super(name);
}Объявление on Animal означает, что этот миксин может быть применен только к классам, которые расширяют Animal. Это гарантирует, что миксин имеет доступ к членам Animal. Без on миксин не знал бы, что name или breathe() существуют.
Если вы попытаетесь использовать ограниченный mixin в несовместимом классе, Dart выдаст ошибку компиляции:
class Robot with Swimming {} // Ошибка! Robot не наследует AnimalЭто ограничение полезно, когда функциональность вашего миксина зависит от конкретных возможностей базового класса. Оно создает более безопасный контракт: миксин гарантирует определенное поведение, но только при наличии основы, необходимой для его корректной работы.
Задание
ЛегкоДавайте создадим систему транспортных средств, которая демонстрирует, как ключевое слово on ограничивает использование примесей (mixins) только конкретными базовыми классами. Вы создадите примесь, которая добавляет функциональность турбо-ускорения, но ее смогут использовать только те классы, которые расширяют базовый класс Vehicle.
Вы организуете свой код в двух файлах:
vehicles.dart: Определите здесь свой базовый класс, ограниченную примесь и типы транспортных средств:- Класс
Vehicleсо свойствомString modelи свойствомint speed. Включите конструктор, принимающий оба значения. Добавьте методaccelerate(), который выводит'$model accelerating to $speed km/h' - Примесь
TurboBoost, ограниченная классомVehicleс помощью ключевого словаon. Эта примесь должна иметь методactivateTurbo(), который выводит'$model TURBO ACTIVATED!', а затем вызываетaccelerate()(оба доступны благодаря ограничениюon Vehicle) - Класс
SportsCar, который расширяетVehicleи использует примесьTurboBoost. Добавьте свойствоString color. Конструктор должен принимать model, speed и color. Добавьте методshowOff(), который выводит'$color $model ready to race!'
- Класс
main.dart: Импортируйте файл с транспортными средствами и продемонстрируйте работу ограниченной примеси:- Создайте объект
SportsCarс моделью'Ferrari', скоростью320и цветом'Red' - Вызовите
showOff() - Вызовите
activateTurbo()
- Создайте объект
Примесь TurboBoost может обращаться к model и вызывать accelerate(), потому что объявление on Vehicle гарантирует, что она будет подмешиваться только в классы, расширяющие Vehicle. Это создает безопасный контракт, при котором примесь точно знает, какие возможности ей доступны.
Ожидаемый вывод:
Red Ferrari ready to race!
Ferrari TURBO ACTIVATED!
Ferrari accelerating to 320 km/hШпаргалка
Ключевое слово on ограничивает использование примеси (mixin) только теми классами, которые расширяют определенный тип. Это позволяет примеси безопасно обращаться к методам и свойствам базового класса.
class Animal {
String name;
Animal(this.name);
void breathe() => print('$name is breathing');
}
mixin Swimming on Animal {
void swim() {
print('$name is swimming'); // Can access 'name' from Animal
breathe(); // Can call Animal's methods
}
}
class Fish extends Animal with Swimming {
Fish(String name) : super(name);
}Объявление on Animal гарантирует, что примесь имеет доступ к членам класса Animal. Без этого примесь не знала бы о существовании name или breathe().
Попытка использовать ограниченную примесь в несовместимом классе приведет к ошибке компиляции:
class Robot with Swimming {} // Ошибка! Robot не расширяет AnimalЭто ограничение полезно, когда функциональность вашей примеси зависит от конкретных возможностей базового класса, создавая более безопасный контракт между примесью и классами, которые её используют.
Попробуйте сами
import 'vehicles.dart';
void main() {
// TODO: Создайте SportsCar с моделью 'Ferrari', скоростью 320 и цветом 'Red'
// TODO: Вызовите showOff()
// TODO: Вызовите activateTurbo()
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий