Menu
Coddy logo textTech

Создание Mixins

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

Теперь, когда вы понимаете, что такое примеси (mixins), давайте посмотрим, как их правильно создавать. Примесь объявляется с использованием ключевого слова mixin вместо class.

mixin Logging {
  void log(String message) {
    print('[LOG] $message');
  }
  
  void logError(String error) {
    print('[ERROR] $error');
  }
}

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

mixin Timestamped {
  DateTime createdAt = DateTime.now();
  
  String get formattedTime => createdAt.toString();
  
  void printTimestamp() {
    print('Created at: $formattedTime');
  }
}

class Document with Timestamped {
  String title;
  Document(this.title);
}

void main() {
  var doc = Document('Report');
  doc.printTimestamp();  // Использует метод миксина
  print(doc.createdAt);  // Использует свойство миксина
}

Когда вы применяете примесь с помощью with, все её члены становятся частью вашего класса. Класс может использовать их напрямую, как и любой код, имеющий экземпляр этого класса. Это делает примеси удобным способом добавления повторно используемой функциональности без сложности иерархий наследования.

challenge icon

Задание

Легко

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

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

  • messaging.dart: Определите здесь вашу примесь и классы сообщений:
    • Примесь Formattable, которая содержит:
      • Свойство String prefix, инициализированное значением '>>>'
      • Геттер separator, который возвращает ' | '
      • Метод format(String text), который возвращает строку [prefix][separator][text]
      • Метод formatBold(String text), который возвращает **[text]**
    • Класс TextMessage, использующий примесь Formattable. Добавьте свойство String sender с конструктором. Включите метод send(String content), который выводит результат вызова format() с аргументом [sender]: [content]
    • Класс AlertMessage, также использующий примесь Formattable. Добавьте свойство String level с конструктором. Включите метод alert(String content), который выводит результат вызова format() с аргументом [[level]] [formatBold(content)]
  • main.dart: Импортируйте ваш файл обмена сообщениями и продемонстрируйте, как оба типа сообщений получают возможности форматирования из примеси:
    • Создайте TextMessage с отправителем 'Alice'
    • Создайте AlertMessage с уровнем 'WARNING'
    • Вызовите send('Hello there!') у текстового сообщения
    • Вызовите alert('System overload') у сообщения об алерте

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

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

>>> | Alice: Hello there!
>>> | [WARNING] **System overload**

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

import 'messaging.dart';

void main() {
  // TODO: Создайте TextMessage с отправителем 'Alice'
  
  // TODO: Создайте AlertMessage с уровнем 'WARNING'
  
  // TODO: Вызовите send('Hello there!') для text message
  
  // TODO: Вызовите alert('System overload') для alert message
}
quiz iconПроверьте себя

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

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