Dart学习-泛型

作者: 你需要一台永动机 | 来源:发表于2018-10-23 18:11 被阅读20次
Dart

如果在API文档上查看基本数组类型List,你会发现该类型实际上是List<E> ,其中<...>注解标记这次集合是一个泛型(参数化的)类 -->一种含有正规类型参数的类型。按照惯例,类型变量通常为单字符名称,例如E,T,S,K,以及V。


为何要使用泛型?

类型安全通常需要泛型,但是它们比仅仅允许代码运行有更多的好处:

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

如果你希望列表仅包含字符串,则可以将其声明为List<String> (将其称为“字符串列表”)。这样,你、你的同事和你的工具就可以发现给列表分配一个非字符串是错误的。这里有一个例子:

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

使用泛型的另一个原因是减少代码重复。泛型允许你在许多类型之间共享单个接口和实现,同时仍然利用静态分析。例如,假设你创建了一个用于缓存对象的接口:

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

你发现需要此接口的字符串特定版本,因此您需要创建另一个接口:

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是代理类型。这是一个占位符,你可以将其视为稍后将定义的类型。


使用集合常量

Lis常量以及map常量都能被参数化。参数常量就像你已经见过的常量那样,除非你在左方括号之前添加<type>(对于List)或者<keyType,valuetype>(对于map)。以下是使用类型化常量的示例:

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

接下来的代码创建一个map,key为Interger类型,value为View类型

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

泛型集合及其包含的类型

dart泛型类型被具体化,这意味着它们在运行时携带它们的类型信息。例如,你可以测试集合的类型:

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

注:相反,Java中的泛型使用擦除,这意味着在运行时移除泛型类型参数。在Java中,你可以测试对象是否是列表,但不能测试它是否是List<String>


限制参数化类型

实现泛型类型时,你可能希望限制其参数的类型。你可以使用extens来执行此操作。

class Foo<T extends SomeBaseClass> {
  // 实现如下...
  String toString() => "Instance of 'Foo<$T>'";
}
//继承
class Extender extends SomeBaseClass {...}

可以使用SomeBaseClass或其任何子类作为泛型参数:

var someBaseClassFoo = Foo<SomeBaseClass>();
var extenderFoo = Foo<Extender>();

也可以不指定泛型参数:

var foo = Foo();
print(foo); // Foo<SomeBaseClass>的对象

指定任何非SomeBaseClass类型都会导致错误:

var foo = Foo<Object>();

使用泛型方法

最初,Dart的一般支持仅限于类。一种称为泛型方法的较新语法允许对方法和函数进行类型参数:

T first<T>(List<T> ts) {
  // 做一些初始化工作或者错误检查,然后...
  T tmp = ts[0];
  // 做一些额外的检查或者处理...
  return tmp;
}

这里,first(<T>)上的泛型类型参数允许你在几个地方使用类型参数T :

  • 在方法的返回类型(T)
  • 作为参数的类型(List<T>)
  • 作为本地变量的类型(T tmp)

PS:本文整理自官方文档,若有发现问题请致邮 caoyanglee92@gmail.com

相关文章

  • Dart学习-泛型

    如果在API文档上查看基本数组类型List,你会发现该类型实际上是List ,其中<...>注解标记这次集合...

  • Dart 泛型

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

  • dart语言学习笔记-4

    泛型 Dart的泛型会一直保留到运行时 Libraries & visibility import和library...

  • Dart 泛型 泛型类 泛型接口

    视频地址https://www.bilibili.com/video/av52490605?p=13 泛型就是解决...

  • Dart基础(八)-泛型

    1.简介:   Dart语言是强类型语言,强类型语言都支持泛型Generics。那么什么是泛型呢?泛型是指代码在使...

  • Dart 泛型 泛型方法 泛型类 泛型接口

    通俗理解:泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验) 1.定义一个泛型,泛型方法...

  • 带你Dart带你Diao之泛型

    泛型学过Java的都应该比较熟悉了,Dart的泛型和Java泛型的核心理念都差不多,在使用中略有不同。 1.使用泛...

  • Dart -- 泛型(Generics)

    如果您查看基本数组类型List的API文档,您将看到该类型实际上是List。<...>符号标记列表为泛型(或...

  • 泛型——Dart(五)

    泛型 从字面意思理解,就是广泛的类型,我们可以在集合中看到泛型的影子: 为什么要有泛型? 以集合为例,假如没有泛型...

  • Flutter/Dart - 泛型

    泛型的定义 通俗理解:泛型就是解决类,接口,方法的复用性、以及对不特定数据类型的支持(类型校验) 接下来我们实现一...

网友评论

    本文标题:Dart学习-泛型

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