Начало работы с объектно-ориентированным Dart | Часть 2
Привет, если вы на пути изучения Flutter/Dart или вам просто интересно почитать про разработку подписывайтесь на мой канал в telegram, буду рад вас видеть! А сегодня поговорим про ООП в DART-е!
Предыдущая статья: Начало работы с объектно-ориентированным Dart | Часть 1
Добавление наследования класса
Проблема
Вы хотите улучшить существующий класс, введя дополнительные функциональные возможности, которых нет в исходном классе.
Решение
Используйте класс с ключевым словом extends, чтобы включить наследование от родительского класса. При использовании ключевого слова extends подкласс наследует функциональность суперкласса. Как объектно-ориентированный язык, Dart предоставляет обширную поддержку классов в каждой новой версии.
Вот пример того, как использовать расширения для добавления наследования классов в Dart:
Обсуждение
В примере кода класс Media расширен за счет подкласса Book. В качестве родительского класса функциональность Media будет доступна любому дочернему классу, как показано на рисунке 5-4.
Наследование позволяет классам принимать методы и свойства суперкласса, как показано на рисунке 5-4. В результате дочерний и родительский классы поддерживают одни и те же свойства и методы.
Следовательно, как показано на рисунке 5-5, класс Book включает свойства и методы, связанные с носителями, в дополнение ко всему, что было явно определено в классе Book.
Мы создаем дочерний подкласс Book, который расширяет класс Media, что означает, что его можно использовать для доступа к методам и переменным, созданным в нем. При использовании подкласса можно переопределить существующие функциональные возможности класса, например, методы и т.д.
Extends обеспечивает наследование общего класса, при котором функциональность родительского (т.е. суперкласса) доступна дочернему (т.е. подклассу). Ключевое слово extends связывает родительский и дочерний классы один к одному, что означает, что множественное наследование не поддерживается. При использовании этой связи имейте в виду, что у вас, скорее всего, будет вызов super.method(), чтобы убедиться, что родительский класс знает об изменениях, внесенных в дочерний.
Примечание: мы не объявляем повторно методы setMediaTitle класса Book. Вместо этого мы можем вызвать этот метод из класса Book, как если бы он был явно объявлен.
Использование расширений является полезным подходом, когда доступны аналогичные структуры данных, для которых потенциально требуются немного разные методы. В примере класс Media представляет собой общую абстракцию, которая настроена для хранения базовой информации. Класс Book - это специализация класса Media, предлагающая возможность добавлять информацию, относящуюся к книге.
Добавление интерфейса класса
Проблема
Вы хотите использовать спецификацию класса, чтобы описать свойства и методы, которые должны быть объявлены при определении объекта.
Решение
Используйте интерфейс класса для определения спецификации объекта, которой должны придерживаться разработчики.
Вот пример того, как определить класс интерфейса в Dart:
Обсуждение
В примере кода интерфейс класса Media используется подклассом Book. Media является родительским классом, поэтому его определения будут доступны любому дочернему классу. Обратите внимание на отсутствие реализации и инициализации, связанных с родительским классом. Вместо этого реализация остается на усмотрение пользователя интерфейса.
Чтобы использовать класс интерфейса, используйте ключевое слово implements. Если вы знакомы с другими языками, вы можете распознать термин абстрактный класс. Абстрактный класс предоставляет определение для класса, но не может использоваться для инициализации объекта.
В примере абстрактный класс с именем Media создает общий интерфейс для мультимедийной информации, как показано на рис. 5-6. Класс Book реализует интерфейс класса Media, что означает, что он отвечает за получение и установку значений, указанных в абстрактном классе. Как свойства, так и методы должны быть определены там, где они переопределяют значения, указанные в интерфейсе. Каждое значение, определенное в классе Book, которое определено в классе Media, имеет префикс @override, означающий, что интерфейс уже определен.
Как правило, абстрактный интерфейс будет использоваться для определения универсальных типов, которые оставляют реализацию разработчику подкласса, подлежащего определению. На рисунке 5-7 можно увидеть взаимосвязь между суперклассом и подклассом.
Подкласс может реализовывать несколько интерфейсов. Однако при создании подкласса следует помнить о том, что иерархия классов не должна быть чрезмерно сложной. Использование интерфейса класса требует, чтобы вы реализовали указанный интерфейс и соответствовали подписи, используемой абстрактным классом.
Типичный вариант использования определения интерфейса - это когда реализация будет рассматриваться как отдельная задача.
Добавление смешивания классов
Проблема
Вы хотите, чтобы существующий класс объединял функциональность из нескольких иерархий классов.
Решение
Используйте Mixins (Миксины), когда требуется функциональность от нескольких классов. Миксины являются мощным инструментом при работе с классами и позволяют объединять информацию из нескольких классов.
Вот пример использования миксина:
Обсуждение
В примере определены два абстрактных класса для хранения информации, относящейся к вариациям шоколадного батончика Snickers. Основной класс шоколадного батончика не содержит требуемой функциональности, поэтому мы включаем новый класс, чтобы расширить возможности программы. На рисунке 5-8 показано, как классы могут быть расширены с помощью ключевого слова mixin.
Ключевое слово with было введено в Dart совсем недавно; однако это то, о чем просили разработчики. Если вы работаете с игровым движком Flame, вы будете часто использовать это ключевое слово. Если вы работали с другими языками, возможно, вам больше знаком термин mixin, в котором несколько классов могут быть объединены для обеспечения дополнительной функциональности.
Mixin может использоваться, как с определениями наследования, так и с определениями интерфейсных классов. Чтобы использовать абстрактный класс с классом CandyBar, мы используем mixin. Mixin требует использования ключевого слова with и объединяет объекты класса.
На рисунке 5-9 суперклассы, на которые даны ссылки, должны оставаться изолированными, что означает, что используемые классы не должны перекрываться. Базовый класс CandyBar не должен переопределять конструктор по умолчанию, используемый в абстрактном или родительском классе.
Как правило, абстрактный класс используется для определения схемы создания объекта. В примере абстрактный класс обозначает ключевые ингредиенты шоколадного батончика. Кроме того, мы создаем класс шоколадного батончика, который можно использовать для хранения общих сведений.
Используйте mixin, чтобы позволить объекту подкласса включать больше функциональных возможностей без необходимости написания специального кода. В примере комбинация родительского класса с абстрактным классом позволяет объединить различные функциональные возможности. В результате этого слияния подкласс CandyBar наделен поведением, относящимся к плитке шоколада и разнообразным сникерсам (т.е. оригинальным по сравнению с версией Crisp). Как только дочерний подкласс создан, его можно использовать для доступа к общим ингредиентам CandyBar.