一、Dart泛型概述
在 Dart 语言中,泛型是指一个类或方法可以接受不同类型的参数。泛型可以帮助我们更好地封装代码,提高代码的可重用性和安全性。
泛型的基本语法如下:
class ClassName<T> {
T method(T arg) {
return arg;
}
}
其中,<T> 表示泛型类型参数,可以是任何合法的 Dart 标识符。在上面的例子中,我们定义了一个泛型类 ClassName,它有一个泛型方法 method,该方法接受一个泛型参数 arg,并返回该参数。
二、Dart泛型擦除
Dart 通过泛型擦除来实现泛型。泛型擦除是指编译器在编译时会将泛型的具体类型替换为 Object 类型,并在必要时进行强制转换。这就意味着,在运行时无法判断泛型的类型。
示例代码如下:
void main() {
List<int> list = [1, 2, 3];
print(list.runtimeType); // 输出:List<int>
processList(list);
}
void processList(List<Object> list) {
print(list.runtimeType); // 输出:List<int>
}
在上面的代码中,我们先定义了一个 List<int> 类型的 list,然后将它作为参数传递给了 processList 方法。在 processList 方法中,我们将参数类型定义为 List<Object>,并输出该参数的类型。我们会发现,输出结果为 List<int>,而不是 List<Object>。这是因为在编译时,泛型类型 int 被擦除,list 的实际类型变为 List<Object>。
三、Dart泛型序列化
Dart 通过序列化和反序列化来实现泛型。序列化是指将对象转换为二进制格式或其他格式,以便于存储或传输。反序列化是指将二进制格式或其他格式转换为对象。
在 Dart 中,我们可以使用 json 库来实现泛型序列化。示例代码如下:
import 'dart:convert';
class Person<T> {
T name;
int age;
Map toJson() {
return {'name': name, 'age': age};
}
static Person fromJson(Map json, T Function(dynamic) fromJsonT) {
return Person<T>()
..name = fromJsonT(json['name'])
..age = json['age'];
}
}
void main() {
var person = Person<String>()
..name = '张三'
..age = 18;
var json = jsonEncode(person.toJson());
print(json); // 输出:{"name":"张三","age":18}
var decodedJson = jsonDecode(json);
var decodedPerson = Person.fromJson(decodedJson, (dynamic name) => name.toString());
print(decodedPerson.name); // 输出:张三
}
在上面的代码中,我们先定义了一个泛型类 Person,通过 toJson 方法将 Person 实例转换为 Map 对象。然后我们将 Map 对象编码为 JSON 字符串,并输出编码结果。接着,我们将 JSON 字符串解码为 Map 对象,并使用 fromJson 方法将 Map 对象转换为 Person 对象。
四、Dart泛型类型限制
Dart 中可以使用 extends 关键字来限制泛型的类型。示例代码如下:
abstract class Animal {
String getName();
}
class Cat implements Animal {
String name;
Cat(this.name);
String getName() => name;
}
class Dog implements Animal {
String name;
Dog(this.name);
String getName() => name;
}
class AnimalList<T extends Animal> {
final List<T> _animals = [];
void add(T animal) {
_animals.add(animal);
}
void printNames() {
for (var animal in _animals) {
print(animal.getName());
}
}
}
void main() {
var animalList = AnimalList<Animal>();
animalList.add(Cat('小花'));
animalList.add(Dog('旺财'));
animalList.printNames(); // 输出:小花 旺财
}
在上面的代码中,我们先定义了一个抽象类 Animal,然后定义了两个实现类 Cat 和 Dog,它们都继承自 Animal。接着,我们定义了一个泛型类 AnimalList,它用于存储 Animal 类型的对象。在 AnimalList 的泛型类型参数 T 上使用 extends 关键字,表示 T 只能是 Animal 或 Animal 的子类。在 AnimalList 类中,我们添加了 add 和 printNames 方法,add 方法用于向 _animals 列表中添加 Animal 类型的对象,printNames 方法用于输出 _animals 中所有对象的名称。
五、Dart泛型类型推断
在 Dart 2.0 中,编译器可以根据变量的类型自动推断泛型类型参数。示例代码如下:
void main() {
var list = <int>[1, 2, 3];
var index = 2;
var item = list[index];
print(item); // 输出:3
var map = <String, int>{
'one': 1,
'two': 2,
'three': 3
};
var key = 'two';
var value = map[key];
print(value); // 输出:2
}
在上面的代码中,我们先定义了一个类型为 List<int> 的 list,然后定义了一个变量 index,它的值为 2。接着,我们根据 index 取出了 list 中的第三个元素,并将结果赋值给变量 item。由于 list 的类型已经被推断为 List<int>,所以编译器可以自动推断出 item 的类型为 int。同理,我们定义了一个类型为 Map<String, int> 的 map,然后根据 key 取出了 map 中的一个值,并将结果赋值给变量 value,编译器可以自动推断出 value 的类型为 int。