Dart(四)--泛型&使用库&异步&生成器&注解

一、泛型

对于泛型想必不用多说,在我们自己写框架或封装时,经常会用到,Dart中泛型的使用基本上于Java差不多,在原理上由于Java泛型为泛型擦除,而Dart是运行时进行即使编译,所以Dart泛型是 固化的

1.类泛型定义

类上使用了泛型后,我们在成员变量上使用,在创建实例时指定泛型类型:

class Cache<T> {
  T value;

  Cache(this.value);
}

main() {
  Cache cache1 = Cache<String>("hi");
  Cache cache2 = Cache<int>(123);
  
  print(cache1.value);
  print(cache2.value);
}

运行结果:

由于Dart支持var方式定义变量,所以直观上来说,使用泛型并没有什么区别,方法上使用该泛型类型

class Cache<T> {
  T value;

  Cache(this.value);

  T getCache() => value;
}
2.方法泛型定义

除了类上定义泛型,单独的方法中可以定义泛型,下面我们在transformValue方法上定义一个泛型F,并且通过一个transform函数返回F类型的结果,transform函数接收一个T类型参数,并返回一个F类型结果,转换实现交由外部调用者实现

class Cache<T> {
  T value;

  Cache(this.value);

  T getCache() => value;

  // 将T类型的value转换为别的类型F
  F transformValue<F>(F transform(T)) {
    return transform(value);
  }
}

main() {
  Cache cache2 = Cache<int>(123);
  
  print(cache2.value);

  // 传入一个匿名函数,返回一个字符串
  print(cache2.transformValue((value) {
    return "hi,${value}";
  }));
}

运行结果:

3.多个泛型

如果你想要定义多个泛型类型,只需要使用,分割,类于方法都可以使用

class N<A, B, C> {}

moreGeneric<A, B, C, D>() {}
4.泛型约束

没有约束的泛型是可以传递任意类型的,有时我们希望对该类型进行一定的约束,如只能为某个类的子类,可以通过T extends OtherClassT泛型进行约束,表示该泛型只能为OtherClass的子类

class O {}

class Foo<T extends O> {
  T value;

  Foo(this.value);
}

main(){
  // 报错提示
  Foo foo1 = Foo<int>(123);
  Foo foo2 = Foo<O>(O());
}

在foo1上会有报错提示:

二、库的使用

Dart中,每个Dart文件都是一个库,使用文件名作为库名,使用library 关键字可以标识为一个库,但可以省略。

下面我们创建一个Dart文件:cacheModule.dart,含有下面的代码:

library;

class Cache<T> {
  T value;

  Cache(this.value);

  T getCache() => value;

  // 将T类型的value转换为别的类型F
  F transformValue<F>(F transform(T)) {
    return transform(value);
  }
}
1.import 导入库

导入后,我们可以直接使用库中的可见内容

import 'package:study1/cacheModule.dart';

main(){
  Cache cache = Cache<String>("hi");
  
  print(cache.value);
}
2._ 库成员可见性

库中含有仅仅内部使用的成员,可以使用_前缀标识,使用后,外部无法使用该成员

library;

...

// 内部类
class _hideClz{}

// 内部方法
_hideFuntion() {}

3.as 解决命名冲突

如两个库module1.dartmodule2.dart中,都含有一个P

class P {}

导入时使用as给库设置别名后,可以解决冲突:

import 'package:study1/module1.dart';
import 'package:study1/module2.dart' as m2;

main() {
  P p = P();
  m2.P p2 = m2.P();
}
4.导入库的部分

在导入时,可以通过show指定导入库的内容,也可以通过hide隐藏导入的内容

// Import only foo.
import 'package:lib1/lib1.dart' show foo;

// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
5.延迟加载库

有时库使用的时机较少,为减少初始化时间,延迟加载库可以在使用时才真正的导入库,使用 deferred as 关键字来标识需要延时加载的代码库:

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

三、异步

Dart对异步的支持比较友好,使用简单,主要分为两大类:FutureStream

1.Future

Future和Java中的概念类似,在方法后面使用async关键字修饰,调用该方法会返回一个Future对象。

Dart中代替了Future对象方法的调用,使用关键字await进行取代,在调用异步方法前使用await修饰后,异步线程会等待 await 异步方法执行完毕后继续执行。同时,await的使用需要在async作用域下

// async修饰后,会返回Future对象
Future<String> getAsyncInfo() async {
  return "hi";
}

main() async {
  // await需在async作用域下调用,会等待异步方法执行完毕
  var result = await getAsyncInfo();
  print("异步调用结果:$result");
}

运行结果:

2.Stream

Stream是专门为上下流作准备的,你可以理解为观察者模式,上流为一个异步任务,并不定时往下流发送内容,下流接收内容并作处理

2.1 await for 异步循环

异步循环语法:await for (var v in stream){}

创建一个文件:

下面我们打开该文件,在async下使用await for获取流中的数据:

import 'dart:convert';
import 'dart:io';

main() async {
  var config =
      File('C:/Users/tyqhc/Documents/flutterworkspace/study1/lib/config.txt');
  Stream<List<int>> inputStream = config.openRead();

  // 将流转为utf-8,逐行读取
  var lines =
      inputStream.transform(utf8.decoder).transform(const LineSplitter());

  await for (final v in lines) {
    print(v);
  }
}

运行结果:

2.2 Stream API

Stream对象还有内置API,可供读取和监听流

使用listen,获取流数据:

import 'dart:convert';
import 'dart:io';

main() {
  var config =
      File('C:/Users/tyqhc/Documents/flutterworkspace/study1/lib/config.txt');
  Stream<List<int>> inputStream = config.openRead();

  var lines =
      inputStream.transform(utf8.decoder).transform(const LineSplitter());

  // listen获取流数据
  lines.listen((event) {
    print(event);
  });
}

除了获取流外,还可以通过transformer 对流数据进行转换,上面我们也使用过:

  var lines =
      inputStream.transform(utf8.decoder).transform(const LineSplitter());

四、生成器

生成器可以生成一连串的值,方式分为同步于异步

1.同步生成器

同步生成器在方法后使用sync*标识,在函数体中使用yield来传递值,返回一个Iterable对象:

Iterable<int> generateInts() sync* {
  for (var i = 0; i < 10; i++) {
    yield i;
  }
}

main() {
  for (final i in generateInts()) {
    print(i);
  }
}
2.异步生成器

异步生成器在方法后使用async*标识,在函数体中同样使用yield来传递值,返回一个Stream对象:

Stream<int> generateIntsStream() async* {
  for (var i = 0; i < 10; i++) {
    yield i;
  }
}

main() async {
  await for (final i in generateIntsStream()) {
    print(i);
  }
}

五、注解

Dart中定义注解方式和类一样,使用时加上@即可:

// 作为注解的类
class MyAnnotation {
  final String name;

  const MyAnnotation(this.name);
}

("hi")
class MyClz {
  ("hi val")
  var value;

  MyClz(this.value);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值