Dart学习笔记(6): 泛型

为什么使用泛型?

泛型常用于需要要求类型安全的情况,但是它也会对代码运行有好处:

  • 适当地指定泛型可以更好地帮助代码生成。
  • 使用泛型可以减少代码重复

比如你想声明一个只能包含 String 类型的数组,你可以将该数组声明为 List<String>(读作“字符串类型的 list”),这样的话就可以很容易避免因为在该数组放入非 String 类变量而导致的诸多问题,同时编译器以及其他阅读代码的人都可以很容易地发现并定位问题:

var names = <String>[];
names.add("jack");
names.add(42); // Error

另一个使用泛型的原因是可以减少重复代码,泛型可以让你在多个不同类型实现之间共享同一个接口声明.比如声明一个方法 返回一个String类型的数据

String getData(String data) {
  return data;
}

此时getData方法只能传入String类型的参数,如果现在要返回一个int类型的数据,又要重新写一个,如下

int getData(int data) {
  return data;
}

这时候可以考虑使用泛型来声明一个类,让不同类型的缓存实现该类做出不同的具体实现即可:

T getData<T>(T data) {
  return data;
}

在上述代码中,T 是一个替代类型。其相当于类型占位符,在开发者调用该接口的时候会指定具体类型。

官网的例子是指定泛型类,具体可以查看Language tour | Dart

//让不同类型的缓存实现该类做出不同的具体实现即可:
abstract class Cache<T> {
  T getByKey(String key);
  void setByKey(String key, T value);
}

具体实现

class FileCache<T> extends Cache<T> {
  @override
  T getByKey(String key) {
    // TODO: implement getByKey
    throw UnimplementedError();
  }
  @override
  void setByKey(String key, T value) {
    print("写入缓存成功key=$key,value=$value");
  }
}


main() {
  var flieCache = FileCache<String>();//限定指定类型为String
  //此时value传入int类型会提示错误。
  flieCache.setByKey("key",
      123); //The argument type 'int' can't be assigned to the parameter type 'String'
  flieCache.setByKey("key", "value");
}

比如现在需要创建个泛型类,需求是传入任意类型的数据添加到List中

class MyList<T> {
  List list = <T>[]; //创建一个空的数组
  void add(T value) {
    list.add(value); //往数据里添加数据
  }
  void getList() {
    print(list);
  }
}

未指定具体类型的,可以传入任意类型,如下

main() {
  var mylist = MyList();
  mylist.add("jack");
  mylist.add(1);
  mylist.getList();
}
输出打印:[jack, 1]

指定类型,比如我要指定集合中只能添加String类型的数据,可以这么写

main() {
  var mylist = MyList<String>();//指定具体的类型,传入其他类型会报错
  mylist.add("jack");
  mylist.add(1);// 报错:The argument type 'int' can't be assigned to the parameter type 'String'
  mylist.getList();
}

限制参数化类型

有时使用泛型的时候,你可能会想限制可作为参数的泛型范围,也就是参数必须是指定类型的子类,这时候可以使用 extends 关键字。

一种常见的非空类型处理方式,是将子类限制继承 Object (而不是默认的 Object?)。

class Foo<T extends Object> {
  // Any type provided to Foo for T must be non-nullable.
}

除了Object之外,还可以对其他类型使用extends。下面是一个扩展SomeBaseClass的例子,这样SomeBaseClass的成员就可以在T类型的对象上被调用:

class Foo<T extends SomeBaseClass> {
  // Implementation goes here...
  String toString() => "Instance of 'Foo<$T>'";
}

class Extender extends SomeBaseClass {...}

这时候就可以使用 SomeBaseClass 或者它的子类来作为泛型参数:

var someBaseClassFoo = Foo<SomeBaseClass>();
var extenderFoo = Foo<Extender>();
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chen_ShengJie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值