美文网首页
Dart之旅08: 范型

Dart之旅08: 范型

作者: suikaJY | 来源:发表于2019-02-13 19:21 被阅读0次

如果你查阅List类的API文档,你会看见类型的写法是List<E>这里的E就是范型,它指代这个类型的实例是某种类型相关的。

为什么使用范型?

范型通常用来保证类型安全,并且他还有更多的好处是你的代码运行:

  • 正确指定泛型类型会产生更好的代码。
  • 您可以使用泛型来减少代码重复。

使用范型可以让工具检测出更多书写错误:

var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // Error

另一个使用原因是可以减少代码重复,比如你想实现一个对象缓存:

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

你会发现你经常能用到字符串缓存,或者Int缓存,所以你又照着原有代码定义了个StringCache或者IntCache之类的:

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

后来你又想定义各种类型的缓存,但建立那么多的类,还都是重复的。你自己都觉得烦。这时你需要用范型来处理这种问题:

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

这里T只是一个占位符,当你真正声明Cache对象的时候需要指明T所指代的类型。

使用集合字面量

集合字面量期望你添加明确的范型:

var names = <String>['Seth', 'Kathy', 'Lars'];
var pages = <String, String>{
  'index.html': 'Homepage',
  'robots.txt': 'Hints for web robots',
  'humans.txt': 'We are people, not machines'
};

使用范型构造函数

var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
var nameSet = Set<String>.from(names);

或者非命名构造函数:

var views = Map<int, View>();

范型集合和它们包含的类型

Dart中的范型是具体化的,这意味着你可以在运行时获取范型的类型,例如你可以测试集合的类型:

var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
print(names is List<String>); // true

注意这里和Java完全相反,Java的范型是可擦除的,你可以判断这个类型是否是List,而不能判断这个类型是否是List<String>

范型限制

和Java类似,限制范型的范围的方式可以使用extends关键字:

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>();

这时你可以指定没有范型的Foo,它的范型默认是SomeBaseClass:

var foo = Foo();
print(foo); // Instance of 'Foo<SomeBaseClass>'

你不可以指定非SomeBaseClass的子类,下面的代码不能通过编译:

var foo = Foo<Object>();

使用范型方法

起初,Dart的范型只能使用类级别的范型,后来可以在方法上定义方法级别的范型了。

T first<T>(List<T> ts) {
  // Do some initial work or error checking, then...
  T tmp = ts[0];
  // Do some additional checking or processing...
  return tmp;
}

类似Java的范型方法,这里定义T时需要在方法名之后定义一个新的范型变量。它有三种用途:

  • 当作方法返回值
  • 当作参数
  • 在方法内部使用

更多信息参考使用范型方法

相关文章

  • Dart之旅08: 范型

    如果你查阅List类的API文档,你会看见类型的写法是List这里的E就是范型,它指代这个类型的实例是某种类...

  • Dart中范型的理解

    刚开始学习flutter时,以下代码都非常熟悉 其中就很奇怪这个尖括号是干什么的,以为是固定写法。 oc语言中类接...

  • CoreJava笔记 - 范型程序设计(2)

    范型代码和Java虚拟机 关键知识:类型擦除Java的范型是编译器层次的范型,而在Java虚拟机上并没有范型类。在...

  • 面试总结 优化

    1.Flutter的setState2.dart的多线程dart的多线程3.java线程池io密集型和Cpu密集型...

  • Dart 泛型

    解决类、接口、方法的复用性以及对不特定数据类型的支持(类型校验) 这种输出指定的类型,可以使用泛型解决 字母 T ...

  • 范型

    <:上界 >:下界 <%视图定界 一定要传隐式转换函数 T隐式转换成order[T][T<%M]关系意味着...

  • 范型

    范型就是不指定类型,用的时候在指定类型使用场景 用在构造函数中

  • 范型

    泛型是jdk1.5使用的新特性。 泛型的好处:1. 将运行时的异常提前至了编译时。2. 避免了无谓的强制类型转换 ...

  • 范型

  • Objective-C 范型

    系统库范型 Objective C支持轻量级的范型。在编写自定义的范型类之前,我们先来看看Cocoa Touch的...

网友评论

      本文标题:Dart之旅08: 范型

      本文链接:https://www.haomeiwen.com/subject/byxjeqtx.html