Menu
Coddy logo textTech

Обобщенные методы

Часть раздела Объектно-ориентированное программирование путешествия по 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]
}

Обобщенные методы обеспечивают тонкий контроль над типобезопасностью на уровне метода, позволяя вашим классам оставаться более простыми и при этом сохраняя преимущества проверки типов на этапе компиляции.

challenge icon

Задание

Легко

Давайте создадим утилиту для преобразования данных, которая продемонстрирует мощь универсальных методов (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
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование