Ответ
Generics в Dart — это реализация параметрического полиморфизма. Они позволяют писать код, который может работать с разными типами данных, оставаясь типобезопасным. Один алгоритм или структура данных становится полиморфной по отношению к типу своих элементов.
Без Generics (отсутствие полиморфизма или небезопасно):
// 1. Код дублируется для каждого типа (нет полиморфизма).
class IntBox { int value; IntBox(this.value); }
class StringBox { String value; StringBox(this.value); }
// 2. Использование dynamic/Object (полиморфно, но небезопасно).
class DynamicBox {
dynamic value; // Потеряна безопасность типов.
DynamicBox(this.value);
}
С Generics (параметрический полиморфизм с безопасностью типов):
// Один полиморфный класс для множества типов.
class Box<T> {
final T value;
Box(this.value);
T getValue() => value;
}
void main() {
// Компилятор выводит конкретный тип для каждого экземпляра.
final intBox = Box<int>(42); // Box<int>
final stringBox = Box('Hello'); // Box<String> (тип выведен)
// Безопасность типов сохраняется.
int number = intBox.getValue(); // OK
// String text = intBox.getValue(); // Ошибка компиляции: type 'int' is not a subtype of 'String'
}
Связь с другими видами полиморфизма в Dart:
- Полиморфизм подтипов (наследование):
class SiberianHusky extends Dog—SiberianHuskyможет использоваться везде, где ожидаетсяDog. - Параметрический полиморфизм (Generics):
List<Dog>может содержатьSiberianHusky,Beagleи т.д., потому что они — подтипыDog. Это показывает, как Generics взаимодействуют с полиморфизмом подтипов.
Практический пример из Flutter:
// Виджет FutureBuilder полиморфен относительно типа данных Future.
FutureBuilder<List<Post>>(
future: _fetchPosts(), // Future<List<Post>>
builder: (context, snapshot) {
if (snapshot.hasData) {
// snapshot.data имеет тип List<Post>? благодаря generics.
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (ctx, i) => PostWidget(snapshot.data![i]), // Тип Post известен.
);
}
return CircularProgressIndicator();
},
)
Таким образом, Generics делают код полиморфным (работает со многими типами), строго типизированным (ошибки ловятся на этапе компиляции) и избегающим дублирования.