Обобщенные методы
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 66 из 110.
Подобно тому, как классы могут быть обобщенными, отдельные методы также могут иметь свои собственные параметры типа. Это полезно, когда вам нужен гибкий метод без необходимости делать весь класс обобщенным.
Обобщенный метод объявляет свой параметр типа перед типом возвращаемого значения:
T findFirst<T>(List<T> items) {
return items.first;
}
void main() {
var firstNumber = findFirst<int>([1, 2, 3]);
var firstWord = findFirst<String>(['hello', 'world']);
print(firstNumber); // 1
print(firstWord); // hello
}Dart часто может вывести тип из аргументов, поэтому вам не всегда нужно указывать его явно:
var result = findFirst([10, 20, 30]); // Dart выводит intОбобщенные методы особенно полезны внутри классов, когда гибкость типов требуется только для определенных операций:
class Printer {
void printItem<T>(T item) {
print('Printing: $item');
}
List<T> duplicate<T>(T item, int count) {
return List.filled(count, item);
}
}
void main() {
var printer = Printer();
printer.printItem<String>('Hello');
printer.printItem(42); // Тип выведен как int
var copies = printer.duplicate('Hi', 3);
print(copies); // [Hi, Hi, Hi]
}Обобщенные методы обеспечивают тонкий контроль над типобезопасностью на уровне метода, позволяя вашим классам оставаться более простыми и при этом сохраняя преимущества проверки типов на этапе компиляции.
Задание
ЛегкоДавайте создадим утилиту для преобразования данных, которая продемонстрирует мощь универсальных методов (generic methods). Вы создадите класс Transformer с методами, которые могут работать с любым типом данных, что обеспечит гибкость без необходимости делать весь класс универсальным.
Вы организуете свой код в двух файлах:
transformer.dart: Создайте классTransformerсо следующими универсальными методами:T getFirst<T>(List<T> items)— возвращает первый элемент из спискаT getLast<T>(List<T> items)— возвращает последний элемент из спискаList<T> repeat<T>(T item, int times)— создает список, содержащий элемент, повторенный указанное количество разvoid printPair<A, B>(A first, B second)— выводит два значения в форматеPair: [first] and [second]
main.dart: Импортируйте файл трансформера и продемонстрируйте работу каждого универсального метода с различными типами данных:- Создайте экземпляр
Transformer - Используйте
getFirstдля[10, 20, 30]и выведите результат - Используйте
getFirstдля['apple', 'banana', 'cherry']и выведите результат - Используйте
getLastдля[1.5, 2.5, 3.5]и выведите результат - Используйте
repeat, чтобы создать список из'Hi', повторенного4раза, и выведите результат - Используйте
repeat, чтобы создать список из7, повторенного3раза, и выведите результат - Используйте
printPairс'Name'и42 - Используйте
printPairс100иtrue
- Создайте экземпляр
Обратите внимание, как каждый метод объявляет свои собственные параметры типа, что позволяет одному и тому же объекту Transformer работать с целыми числами, строками, числами с плавающей запятой и логическими значениями — и все это с полной типизацией. Метод printPair демонстрирует использование двух параметров типа в одном методе.
Ожидаемый вывод:
10
apple
3.5
[Hi, Hi, Hi, Hi]
[7, 7, 7]
Pair: Name and 42
Pair: 100 and trueШпаргалка
Обобщенные методы объявляют параметры типа перед типом возвращаемого значения, что позволяет отдельным методам быть гибкими без необходимости делать весь класс обобщенным:
T findFirst<T>(List<T> items) {
return items.first;
}Dart может выводить тип из аргументов, поэтому явное указание типа необязательно:
var result = findFirst([10, 20, 30]); // Dart выводит intОбобщенные методы могут использоваться внутри необобщенных классов:
class Printer {
void printItem<T>(T item) {
print('Printing: $item');
}
List<T> duplicate<T>(T item, int count) {
return List.filled(count, item);
}
}Методы могут объявлять несколько параметров типа:
void printPair<A, B>(A first, B second) {
print('Pair: $first and $second');
}Попробуйте сами
import 'transformer.dart';
void main() {
// Создайте экземпляр Transformer
var transformer = Transformer();
// TODO: Используйте getFirst для [10, 20, 30] и выведите результат
// TODO: Используйте getFirst для ['apple', 'banana', 'cherry'] и выведите результат
// TODO: Используйте getLast для [1.5, 2.5, 3.5] и выведите результат
// TODO: Используйте repeat, чтобы создать список из 'Hi', повторенного 4 раза, и выведите его
// TODO: Используйте repeat, чтобы создать список из 7, повторенной 3 раза, и выведите его
// TODO: Используйте printPair с 'Name' и 42
// TODO: Используйте printPair с 100 и true
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий