愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

Dart学习笔记(九):可调用类、isolates、typedefs、元数据与注释

一、可调用类

Dart中,如果一个类里实现了call()方法,则可以把实例对象当做方法来调用。因此实现了call()方法的类称之为Callable classes,如下是一个例子:

class Calculator {
    call(String operate, int a, int b) {
        if (operate == '+') {
            return a + b;
        }
    }
}

main() {
    var calc = new Calculator();
    var sum = calc('+', 1, 2);
    print(sum); // 输出:3
}

二、isolates

现代浏览器和移动端浏览器都是运行在多核CPU上的,如果要充分利用这些CPU,通常的做法是使用共享内存来保证多线程的正确执行。但是多线程会导致在数据共享时因为同步等原因,带来一些潜在的问题,甚至导致代码出错。但是Dart代码并不运行在线程模型中,而是隔离的isolates模型,每个isolate都有自己的堆内存,并且确保每个isolate的状态都不能被其他isolate所访问

三、Typedefs

Dart中,方法也是对象,可以使用typedeffunction-type alias来为方法类型指定别名。例子如下:

1、未使用别名

class SortedCollection {
    Function compare;
    SortedCollection(int f(Object a, Object b)) {
        compare = f;
    }
}

int sort(Object a, Object b) {
    // ...
}

main() {
    SortedCollection collection = new SortedCollection(sort);
    assert(coll.compare is Function);
}

以上代码,存在如下的问题:

  • compare = f,导致类型放大成了Function类型,丢失了原来的类型(Object, Object) -> int
  • 不能方便地做更精细的类型判断

因此,Typedefs的好处来了

2、使用别名

我们可以使用typedef关键字定义一个类型别名,如下:

typedef int Compare(Object a, Object b);

class SortedCollection {
    Compare compare;
    SortedCollection(this.compare);
}

int sort(Object a, Object b) {
    // ...
}

main() {
    SortedCollection collection = new SortedCollection(sort);
    assert(coll.compare is Function);
    assert(coll.compare is Compare);
}

于是,我们可以发现,原来的两个问题就都解决了。

注意: 目前Dart中,typedef只能用于Function类型上

四、元数据

元数据注解可以给代码中添加额外的信息,其语法以@开头,后面跟着一个编译时常量或者调用一个常量构造函数Dart中的元数据注解,其实就相当于JavaScript的装饰器。但是,Dart中默认支持以下的元数据注解:

  • @deprecated
  • @override
  • @proxy

示例如下:

class Television {
    @deprecated
    void activate() {
        turnOn();
    }

    void turnOn() {
        // ...
    }
}

我们可以定义自己的元数据,只要它是一个编译时常量或者是常量构造函数,如:

class todo {
    final String who;
    final String what;
    const todo(this.who, this.what);
}

@todo('Ruphi', 'to make the function do something')
void doSomething() {
    // ...
}

元数据可以用于以下这些场景之前:

  • library
  • class
  • typedef
  • type parameter
  • constructor
  • factory
  • function
  • field
  • parameter
  • 变量声明
  • import
  • export

此后,通过反射,便可在运行时获取元数据信息

五、注释

Dart中支持三种类型的注释:

  • 单行注释
  • 多行注释
  • 文档注释

其中单行注释是//开头的注释,多行注释是/**/包围的注释,这和其他语言是一致的。不同的是,Dart中支持一种特殊的注释,称之为文档注释
文档注释有两种形式:

  • ///开始的单行注释
  • /**开始,*/结束的多行注释

Dart为文档注释赋予了特殊的语义,即:编译器会忽略除了中括号以外的内容,中括号中可以引用classesmethodsfieldstop-level variablesfunctionsparameters,在生成文档后,就会生成一个连接到相应API文档的链接。如:

class Llama {
    String name;
    
    /// Feeds your llama [Food]
    ///
    /// The typical llama eats one bale of hay per week
    void feed(Food food) {
        // ...
    }

    /// Exercises your llama with an [activity] for 
    /// [timeLimit] minutes. 
    void exercise(Activtiy activity, int timeLimit) {
        // ...
    }
}
``