Dart 学习笔记-泛型、库的使用

参考:https://www.dartcn.com/guides/language/language-tour#%E6%B3%9B%E5%9E%8B

泛型

API文档中你会发现基础数组类型 List 的实际类型是 List<E><…> 符号将List标记为 泛型 (或 参数化) 类型。 这种类型具有形式化的参数。 通常情况下,使用一个字母来代表类型参数, 例如 E, T, S, K, 和 V等。

为什么使用泛型

在类型安全上通常需要泛型支持, 它的好处不仅仅是保证代码的正常运行:

  • 正确指定泛型类型可以提高代码质量。
    例如:
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);
}

限制泛型类型

使用泛型类型的时候, 可以使用 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>();

也可以不指定泛型参数:

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

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

var foo = Foo<Object>(); // 报错

import 和 library指令可以用来创建一个模块化的,可共享的代码库。 库不仅提供了 API ,而且对代码起到了封装的作用: 以下划线 (_) 开头的标识符仅在库内可见。 每个 Dart 应用程序都是一个库 ,虽然没有使用 library指令。

使用库

通过import 指定一个库命名空间中的内如如何在另一个库中使用。
例如,Dart Web应用程序通常使用 dart:html库,它们可以像这样导入:

import 'dart:html';

import 参数只需要一个指向库的 URI

  • 对于内置库,URI 拥有自己特殊的dart:方案。
  • 对于其他的库,使用系统文件路径或者 package:方案 。
    例如:
import 'package:test/test.dart';

指定库前缀

如果导入两个存在冲突标识符的库, 则可以为这两个库,或者其中一个指定前缀。
例如,如果 library1 和 library2 都有一个 Element 类, 那么可以通过下面的方式处理:

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

// 使用 lib1 中的 Element。
Element element1 = Element();

// 使用 lib2 中的 Element。
lib2.Element element2 = lib2.Element();

导入库的一部分

如果你只使用库的一部分功能,则可以选择需要导入的 内容。例如:

// 只导入 foo 功能
import 'package:lib1/lib1.dart' show foo;

// 导入除了 foo 之外的所有功能
import 'package:lib2/lib2.dart' hide foo;

延迟加载库

Deferred loading (也称之为 lazy loading)可以让应用在需要的时候再加载库。 下面是一些使用延迟加载库的场景:

  • 减少 APP 的启动时间。
  • 执行 A/B 测试,例如 尝试各种算法的 不同实现。
  • 加载很少使用的功能,例如可选的屏幕和对话框。

要延迟加载一个库,需要先使用 deferred as 来导入:
当需要使用的时候,使用库标识符调用 loadLibrary() 函数来加载库:

import 'package:greetings/hello.dart' deferred as hello;

Future greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}

在一个库上你可以多次调用 loadLibrary()函数。但是该库只是载入一次。
使用延迟加载库的时候,请注意一下问题:

  • 延迟加载库的常量在导入的时候是不可用的。 只有当库加载完毕的时候,库中常量才可以使用。
  • 在导入文件的时候无法使用延迟库中的类型。 如果你需要使用类型,则考虑把接口类型移动到另外一个库中, 让两个库都分别导入这个接口库。
  • Dart 隐含的把 loadLibrary() 函数导入到使用 deferred as 的命名空间 中。 loadLibrary() 方法返回一个 Future对象,也就是异步函数。
发布了180 篇原创文章 · 获赞 76 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/ITxiaodong/article/details/104168873