Ответ
Generics в Dart — это синтаксис и система типов, позволяющие писать код, параметризованный типами. Это основа для создания типобезопасных коллекций и утилит, которые являются краеугольным камнем языка.
Зачем они нужны? Без Generics пришлось бы использовать тип dynamic или Object, что лишает проверки типов и требует постоянных приведений (casts).
// Без Generics (небезопасно и неудобно)
class OldBox {
final Object value;
OldBox(this.value);
}
void main() {
var box = OldBox('строка');
int length = (box.value as String).length; // Требуется явное приведение типа
}
// С Generics (безопасно и удобно)
class NewBox<T> {
final T value;
NewBox(this.value);
}
void main() {
var box = NewBox<String>('строка');
int length = box.value.length; // Компилятор знает, что value — это String
}
Generics в функциях и методах:
// Функция, возвращающая первый элемент списка любого типа
T getFirst<T>(List<T> list) {
if (list.isEmpty) throw StateError('List is empty');
return list.first;
}
void main() {
print(getFirst<int>([1, 2, 3])); // 1
print(getFirst<String>(['a', 'b'])); // a
// Тип часто выводится автоматически:
print(getFirst([1.5, 2.7])); // 1.5, T выводится как double
}
Использование в Flutter API:
// FutureBuilder автоматически выводит тип из Future<T>
FutureBuilder<List<User>>(
future: fetchUsers(),
builder: (context, snapshot) {
if (snapshot.hasData) {
// snapshot.data имеет тип List<User>
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (ctx, i) => Text(snapshot.data![i].name),
);
}
return CircularProgressIndicator();
},
)