生成器
通过在函数上添加关键字 sync*/async*
并在函数中使用yield
关键字来传递值,可以生成一连串的值。
- 通过使用
sync*
关键字并返回Iterable
对象,返回一个同步生成器
Iterable<int> generate(int n) sync* {
while(n<10) {
yield n;
}
}
- 通过使用
async*
关键字并返回Stream
对象,返回一个异步生成器
Stream<int> generate(int n) async* {
while(n<10) {
yield n;
}
}
如果需要通过递归调用,可以使用 yield*
来提升执行性能。
Iterable<int> generate(int n) sync* {
while(n<10){
yield n;
yield* generate(n-1);
}
}
可调用类
通过实现call()
函数来实现通过函数的方式来使用类的实例;所有的类都可以定义一个call()
的函数,这个函数和普通的函数一样,可以定义返回值和参数。
class Test{
String call(String a,String b, String c) => 'a=${a},b=>${b}, c=>${c}';
}
void mian(){
var test = Test();
print(test('hello','dart','call')); // a=>hello,b=>dart,c=>call
}
隔离区
在Dart中,没有线程的概念,而是通过isolate
代替了线程,所有的Dart代码都是运行在一个isolate
中。isolate
可以理解为一个单独的进程(并不是,只是为了类比),每个isolate
都有自己的堆内存,其他isolate
都无法访问;每个isolate
都有一个执行线程。
isolate之间的通信:
// 创建一个消息接收器
ReceivePort rvp = ReceivePort();
// 创建一个新的isolate
Isolate.spvn(isoLateNew, rvp.sendPort);
// 接收消息
rvp.listen((message){
if(message is SendPort) {
message.send('hello, connected');
}else{
print(message);
}
})
void isolateNew(SendPort sendPort) {
// 创建消息接收器
ReceivePort rvp = ReceivePort();
// 发送自身的消息发送器
sendPort.send(rvp.sendPort);
// 发送消息
sendPort.send('hello,this is isolateNew, connecting');
// 监听消息
rvp.listen((message){
print(message);
})
}
Typedefs
使用关键字 typedef
来给某一类型定义类型别名,来简化复杂类型。
typedef IntList = List<int>;
IntList li = [1,2,3];
类型别名也可以参数化类型
typedef ListMapper<T> = Map<T,List<T>>;
Map<String,List<String>> m1 = {};
// m1 & m2 效果一样
ListMap<String> m2 = {};
元数据
使用元数据可以为代码增加一些额外的信息。元数据注解以@
开头,其后紧跟一个编译时常量,或者调用一个常量构造函数。
class Todo {
final String who;
final String what;
const Todo(this.who, this.what);
}
@Todo('seph', 'Implement this function late')
void doSomething() {
}
元数据可以在 library
、class
、typedef
、type parameter
、 constructor
、factory
、function
、field
、parameter
或者 variable
声明之前使用,也可以在 import
或 export
之前使用。可使用反射在运行时获取元数据信息。