header-bg.jpg
Dart 面向对象之泛型
发表于 2019-08-20 17:16
|
分类于 Dart
|
评论次数 0
|
阅读次数 1946

QQ图片20190703111655.png

Dart 中的集合(List、Map 等)可以包含多种类型的值,如果我们想强制规定集合中只包含一种类型的值,可以使用泛型来解决这个问题。

只包含一种类型的集合一般被称作类型安全集合类型安全是一种编程功能,可确保某个内存块只能包含特定数据类型的数据。

泛型的语法

泛型的语法非常简单,使用 <> 标识符即可声明泛型,例如声明一个只包含 StringList

实例化构造函数的形式:

var names = List<String>();
var pages = Map<String, String>();

声明字面量的形式:

var names = <String>[];
var pages = <String, String>{};

泛型的优点

类型安全

泛型是类型安全的,因此我们在使用时必须使用指定的数据类型,否则编辑器将会提示错误,代码在运行后也会报错,例如:

void main() {
  var names = <String>[];
  names.addAll(['Adele', 'Sia', 'Enya']);
  names.add('Beyonce');
  print(names);// output: [Adele, Sia, Enya, Beyonce]
  names.add(123);// Try changing the type of the parameter, or casting the argument to 'String'.
}

上面的代码中,names 变量使用了泛型,规定它是一个只包含 String 成员的 List,当往 names 中追加 int 类型的成员时,编辑器会直接提示错误,并且运行后会出错。

减少重复代码

泛型可以在多种类型之间定义同一个实现,同时还可以继续使用检查模式和静态分析工具提供的代码分析功能。

例如,我们创建了一个缓存 Object 的接口:

abstract class ObjectCache {
  Object getByKey(String key);
  setByKey(String key, Object value);
}

接着再创建一个缓存 String 的接口:

abstract class StringCache {
  String getByKey(String key);
  setByKey(String key, String value);
}

如果后面需要创建一个缓存 intMap 等等类型的接口,则还需要重复以上代码,非常麻烦。此时使用泛型就可以解决这个代码重复的问题,例如:

abstract class StringCache<T> {
  T getByKey(String key);
  setByKey(String key, T value);
}

上面的代码中,T 是一个类型的占位符,你也可以将 T 换成其他字母。如果开发者需要调用该接口,则必须指定某个具体类型。

泛型的使用

限制泛型类型

当我们需要限制泛型的具体类型时,可以使用 extends 关键字进行约束:

class Human {

}

class Man extends Human {

}

class Person<T extends Human> {
  
  toString() => 'Instance of Human<$T>';
}

void main() {
  final leo = Person<Man>();
  final sia = Person<Human>();
  final bob = Person();
  print(leo);// output: Instance of Human<Man>
  print(sia);// output: Instance of Human<Human>
  print(bob);// output: Instance of Human<Human>
}

上面的代码中,泛型参数被约束为 Human 类或 Human 子类。

使用泛型函数

Dart 1.21 之后的版本开始支持泛型函数,用法如下:

T first<T>(List<T> lists) {
  T tmp = lists[0];
  return tmp;
}

void main() {
  final str = first<String>(['foo']);
  print(str);// output: foo
}

上面的代码中,泛型函数 first<T> 的泛型参数 T 可以在如下地方使用:

发布评论
还没有评论,快来抢沙发吧!