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