Обобщенные классы
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy. Урок 65 из 110.
Вы уже видели, как встроенные коллекции Dart, такие как List<String>, используют параметры типа. Теперь пришло время создать собственные обобщённые классы, работающие с любым указанным вами типом.
Класс generic использует параметр типа (обычно T) в качестве заполнителя для фактического типа, который будет указан при создании экземпляра:
class Box<T> {
T content;
Box(this.content);
T getContent() => content;
}
void main() {
var stringBox = Box<String>('Hello');
var intBox = Box<int>(42);
print(stringBox.getContent()); // Hello
print(intBox.getContent()); // 42
}T выступает в роли переменной типа — когда вы создаёте Box<String>, каждый T в классе становится String. Это обеспечивает безопасность типов без необходимости писать отдельные классы для каждого типа.
Вы можете использовать несколько параметров типа, когда вашему классу нужно работать более чем с одним типом:
class Pair<K, V> {
K first;
V second;
Pair(this.first, this.second);
}
void main() {
var pair = Pair<String, int>('age', 25);
print('${pair.first}: ${pair.second}'); // age: 25
}Классы generic — основа повторно используемого и типобезопасного кода. Вместо дублирования логики для разных типов или потери информации о типах при использовании dynamic generics позволяют писать гибкий код, который компилятор всё ещё может проверять.
Задание
ЛегкоДавайте создадим систему упаковки подарков, которая использует generic классы для создания гибких контейнеров для разных типов элементов. Вы создадите generic класс Wrapper, который может оборачивать любой тип content, и класс GiftBox с двумя параметрами типа для объединения подарка с сообщением на открытке.
Вы организуете код в два файла:
wrapper.dart: Define здесь ваши generic классы:- generic класс
Wrapper<T>со свойствомT contentи Constructor. Добавьте Methodunwrap(), который returns content, и Methoddescribe(), который выводитWrapped: [content] - generic класс
GiftBox<G, C>с двумя свойствами:G giftиC card. Добавьте Constructor и Methodopen(), который выводитGift: [gift]в одной строке иCard: [card]в следующей строке
- generic класс
main.dart: импортируйте файл wrapper и продемонстрируйте generic классы с разными типами:- Create
Wrapper<String>, содержащий'Chocolate', и calldescribe() - Create
Wrapper<int>, содержащий42, и calldescribe() - Create
Wrapper<double>, содержащий3.14, и calldescribe() - Выведите пустую строку
- Create
GiftBox<String, String>с gift'Teddy Bear'и card'Happy Birthday!', затем callopen() - Выведите пустую строку
- Create
GiftBox<int, String>с gift100(представляющим сумму подарочной карты) и card'Congratulations!', затем callopen()
- Create
Обратите внимание, как один и тот же класс Wrapper без проблем работает со строками, целыми числами и числами double. Класс GiftBox демонстрирует использование двух параметров типа для объединения разных типов: gift может иметь любой тип, а сообщение на card остаётся строкой.
Ожидаемый результат:
Wrapped: Chocolate
Wrapped: 42
Wrapped: 3.14
Gift: Teddy Bear
Card: Happy Birthday!
Gift: 100
Card: Congratulations!Попробуйте сами
import 'wrapper.dart';
void main() {
// TODO: Создайте Wrapper<String>, содержащий 'Chocolate', и вызовите describe()
// TODO: Создайте Wrapper<int>, содержащий 42, и вызовите describe()
// TODO: Создайте Wrapper<double>, содержащий 3.14, и вызовите describe()
// TODO: Выведите пустую строку
// TODO: Create a GiftBox<String, String> with gift 'Teddy Bear'
// and card 'Happy Birthday!', then call open()
// TODO: Выведите пустую строку
// TODO: Создайте GiftBox<int, String> с подарком 100
// and card 'Congratulations!', then call open()
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн РепозиторийПотренируйтесь самостоятельно: Онлайн-компилятор Dart