Вызываемые классы
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 84 из 110.
В Dart вы можете сделать экземпляры класса вызываемыми как функции, реализовав метод call(). Это позволяет использовать объект с синтаксисом вызова функции — используя круглые скобки непосредственно для экземпляра.
class Multiplier {
final int factor;
Multiplier(this.factor);
int call(int value) {
return value * factor;
}
}
void main() {
var double = Multiplier(2);
var triple = Multiplier(3);
print(double(5)); // 10 - вызов объекта как функции
print(triple(5)); // 15
}Когда вы пишете double(5), Dart автоматически вызывает метод call() с 5 в качестве аргумента. Объект ведет себя как функция, сохраняя при этом свое состояние (поле factor).
Метод call() может иметь любую сигнатуру — несколько параметров, необязательные параметры или даже возвращать различные типы:
class Greeter {
final String greeting;
Greeter(this.greeting);
String call(String name, {String punctuation = '!'}) {
return '$greeting, $name$punctuation';
}
}
void main() {
var hello = Greeter('Hello');
print(hello('Alice')); // Hello, Alice!
print(hello('Bob', punctuation: '.')); // Hello, Bob.
}Вызываемые классы полезны, когда вам нужно поведение, подобное функции, в сочетании с состоянием или конфигурацией. Они обычно используются для создания многократно используемых операций, валидаторов или преобразований, которым необходимо запоминать настройки между вызовами.
Задание
ЛегкоДавайте создадим систему форматирования текста, используя вызываемые классы (callable classes)! Вы создадите объекты, которые можно вызывать как функции для преобразования текста различными способами, сохраняя при этом их собственные настройки конфигурации.
Вы организуете свой код в двух файлах:
formatters.dart: Создайте два вызываемых класса, которые преобразуют текст:- Класс
Wrapper, который оборачивает текст префиксом и суффиксом. Он должен хранитьString prefixиString suffix, и при вызове с параметромString textвозвращать текст, обернутый между префиксом и суффиксом. - Класс
Repeater, который повторяет текст определенное количество раз. Он должен хранить значениеint times, и при вызове с параметромString textвозвращать текст, повторенный указанное количество раз с пробелом между каждым повторением.
- Класс
main.dart: Импортируйте ваши форматировщики и продемонстрируйте, как работают вызываемые классы:- Создайте
Wrapperс префиксом"["и суффиксом"]" - Создайте еще один
Wrapperс префиксом"***"и суффиксом"***" - Создайте
Repeater, который повторяет 3 раза - Вызовите первый wrapper со строкой
"Hello"и выведите результат - Вызовите второй wrapper со строкой
"Important"и выведите результат - Вызовите repeater со строкой
"Go"и выведите результат - Наконец, объедините их: вызовите первый wrapper с результатом вызова repeater со строкой
"Dart"и выведите результат
- Создайте
Обратите внимание, как каждый объект-форматировщик запоминает свою конфигурацию и может быть вызван напрямую с помощью круглых скобок, точно так же, как функция!
Ожидаемый вывод:
[Hello]
***Important***
Go Go Go
[Dart Dart Dart]Шпаргалка
Классы можно сделать вызываемыми, как функции, реализовав метод call():
class Multiplier {
final int factor;
Multiplier(this.factor);
int call(int value) {
return value * factor;
}
}
void main() {
var double = Multiplier(2);
print(double(5)); // 10 - вызов объекта как функции
}Метод call() может иметь любую сигнатуру с несколькими параметрами, необязательными параметрами или различными типами возвращаемых значений:
class Greeter {
final String greeting;
Greeter(this.greeting);
String call(String name, {String punctuation = '!'}) {
return '$greeting, $name$punctuation';
}
}
void main() {
var hello = Greeter('Hello');
print(hello('Alice')); // Hello, Alice!
print(hello('Bob', punctuation: '.')); // Hello, Bob.
}Вызываемые классы полезны для создания поведения, подобного функциям, в сочетании с состоянием или конфигурацией.
Попробуйте сами
import 'formatters.dart';
void main() {
// TODO: Создать Wrapper с префиксом "[" и суффиксом "]"
// TODO: Создать еще один Wrapper с префиксом "***" и суффиксом "***"
// TODO: Создать Repeater, который повторяет 3 раза
// TODO: Вызвать первый wrapper со строкой "Hello" и вывести результат
// TODO: Вызвать второй wrapper со строкой "Important" и вывести результат
// TODO: Вызвать repeater со строкой "Go" и вывести результат
// TODO: Комбинировать их: вызвать первый wrapper с результатом
// вызова repeater со строкой "Dart", и вывести результат
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий