Menu
Coddy logo textTech

Ключевое слово 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

Это ограничение полезно, когда функциональность вашего миксина зависит от конкретных возможностей базового класса. Оно создает более безопасный контракт: миксин гарантирует определенное поведение, но только при наличии основы, необходимой для его корректной работы.

challenge icon

Задание

Легко

Давайте создадим систему транспортных средств, которая демонстрирует, как ключевое слово 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()
}
quiz iconПроверьте себя

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

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