Интерфейсы в Dart
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 45 из 110.
В отличие от многих языков, имеющих специальное ключевое слово interface, Dart использует другой подход. В Dart каждый класс автоматически определяет интерфейс. Этот интерфейс состоит из всех публичных членов (методов и свойств), которые объявляет класс.
Когда вы хотите, чтобы класс гарантировал предоставление определенной функциональности без наследования реализации, вы используете ключевое слово implements:
class Printer {
void printDocument(String content) {
print('Printing: $content');
}
}
class Scanner {
void scan() {
print('Scanning document');
}
}
// MultiFunctionDevice должен реализовать ВСЕ методы обоих классов
class MultiFunctionDevice implements Printer, Scanner {
@override
void printDocument(String content) {
print('MFD printing: $content');
}
@override
void scan() {
print('MFD scanning');
}
}Ключевое отличие от extends заключается в том, что implements не наследует никакой код. Вы должны предоставить собственную реализацию для каждого метода и свойства, определенных в интерфейсе. Это контракт — вы обещаете, что ваш класс будет обладать этими возможностями, но именно вы решаете, как именно они работают.
Этот подход дает Dart гибкость. Вы можете использовать абстрактные классы, когда хотите определить интерфейсы без реализации, или использовать обычные классы в качестве интерфейсов, когда это имеет смысл. В следующем уроке более подробно рассматривается, как работает концепция «неявного интерфейса» (implicit interface).
Задание
ЛегкоДавайте создадим систему медиаплеера, которая демонстрирует работу ключевого слова implements в Dart. Вы создадите классы, которые будут служить интерфейсами, а затем реализуете их в одном устройстве, сочетающем в себе несколько возможностей.
Вы организуете свой код в двух файлах:
media.dart: Определите здесь ваши классы-интерфейсы и реализующий класс:- Класс
AudioPlayerс методомplayAudio(String track), который выводитPlaying audio: [track] - Класс
VideoPlayerс методомplayVideo(String title), который выводитPlaying video: [title] - Класс
SmartTV, который реализует какAudioPlayer, так иVideoPlayer. Посколькуimplementsне наследует никакой код, вы должны предоставить собственные реализации для обоих методов. ВашSmartTVдолжен выводитьSmartTV audio: [track]для аудио иSmartTV video: [title]для видео
- Класс
main.dart: Импортируйте ваш файл media и продемонстрируйте, как один класс может реализовывать несколько интерфейсов:- Создайте экземпляр
SmartTV - Вызовите
playAudio('Jazz Collection') - Вызовите
playVideo('Nature Documentary')
- Создайте экземпляр
Обратите внимание, что SmartTV должен предоставить собственную реализацию для каждого метода из обоих интерфейсов — он не наследует оригинальные реализации от AudioPlayer или VideoPlayer. В этом заключается ключевое отличие между implements и extends.
Ожидаемый вывод:
SmartTV audio: Jazz Collection
SmartTV video: Nature DocumentaryШпаргалка
В Dart каждый класс автоматически определяет интерфейс, состоящий из всех его публичных членов. Чтобы реализовать интерфейс без наследования кода, используйте ключевое слово implements:
class Printer {
void printDocument(String content) {
print('Printing: $content');
}
}
class Scanner {
void scan() {
print('Scanning document');
}
}
// Необходимо реализовать ВСЕ методы из обоих классов
class MultiFunctionDevice implements Printer, Scanner {
@override
void printDocument(String content) {
print('MFD printing: $content');
}
@override
void scan() {
print('MFD scanning');
}
}Ключевые отличия от extends:
implementsне наследует реализацию кода- Вы должны предоставить собственную реализацию для каждого метода и свойства
- Класс может реализовывать несколько интерфейсов
- Это контракт, гарантирующий, что ваш класс будет обладать этими возможностями
Попробуйте сами
import 'media.dart';
void main() {
// TODO: Создайте экземпляр SmartTV
// TODO: Вызовите playAudio('Jazz Collection')
// TODO: Вызовите playVideo('Nature Documentary')
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий