闲话Dart精髓语法5--类与对象篇

好了, 小伙伴们, 今天让我们来一起来过一下本系列中最麻烦的类和对象. 这部分不论在什么编程语言中, 都是值得我们深入掌握的. 毕竟我们通常都是会构建很多个自己的自定义类来支撑起我们项目中各式各样的业务需求.
好了, 分隔线后我们进入正题.
1. Classes:
a. Dart是OO(object-oriented)类型的语言. 而且是mixin-based inheritance. 跟java一样, 所有类继承自Object. 重要的事情戳三遍!!! 这里要mark下这个mixin-based inheritance. 意思是在Dart里, 尽管所有的class都是只有一个父类, 一个class body可以在多个类的层级中使用. 这个到底是什么意思呢? 别着急, 我们会细谈mixin.
b. 创建一个对象, 当然是用new和constructor一起. 举例如下.

c. 重要的事情戳三遍!!! 注意, 在Dart 2里我们可以省略constructor之前的new. 这个在Flutter Beta 2我们已经可以试用了. 真的是很爽.

d. 用.操作符来访问成员变量以及成员函数. 没啥说的, 到哪里都是这样.

e. 用?. 来避免null. 这个和kotlin一样, 防null的.

f. 重要的事情戳三遍!!! 有一些类提供constant的构造函数. 可以用于创建一个compile-time constant. 注意, Dart 2允许我们省略const关键字.

g. 重要的事情戳三遍!!! 当我们构建2个相同的compile-time constants的话, 会生成同一个权威的instance. 如下例中的a和b是一个instance.

h. 由于Dart里的object很多时候都是dynamic的, 所以如果我们想知道一个变量在runtime的时候的类型, 可以使用.runtimeType来查询.

2. Instance Variables:
a. 没有设定初始值的实例变量为null. 重要的事情戳三遍!!!
b. 实例变量自动带getter function. 如果这个实例变量没有用final定义, 也会自动生成setter.

3. Constructors:
a. 注意, Dart建议我们仅仅应该在name conflict的时候在构造函数中使用this.

b. 重要的事情戳三遍!!! Dart有简单的写构造函数的方法. 举例如下图. 这种用法在Flutter的各种sample中到处都是的说.

c. Default Constructors. 如果我们没有命名构造函数, 那么Dart会帮我们创建一个空参的构造函数.
d. 构造函数在Dart里不可继承. 重要的事情戳三遍!!!
e. Named constructor. 这个很有意思. 如果我们想有多个构造函数. 需要我们不同命名.

f. 如果要在constructor中使用super的话, 一定要放在最后. 具体可参考Effective Dart: Usage | Dart. 举例如下图.

g. Redirecting constructors. 这种constructor没有自己的body, 通过使用:来delegate main constructor.

h. Constant constructors. 重要的事情戳三遍!!! 这个东东超级有用. 如果我们的一个class产生的对象永不变化的话, 我们可以把这些对象变为compile-time的constant. 那么怎么做到这样呢? 重点来了, 用constant constructor. 注意, constant constructor里的实例变量是final的. 在刚开始玩Flutter的时候, 我们经常要使用new或者const来创建widget. 很容易困惑于到底应该什么时候使用new或是const. 好消息是, Dart2后我们可以在创建对象的时候省略new和const. 这样会使我们的widget tree更简洁. 扯远了, 汗.

i. Factory constructors. 重要的事情戳三遍!!! 这个也超级有用. 如果我们不想每次创建一个新的instance的话, 就可以用这个. 调用方还是一样, 用new来调用. 但是底层实际上有可能没有创建一个新的实例.

4. Methods:
a. Instance methods, 实例方法是可以访问this的. 这个没啥可说的, 到哪里都一样.
b. Getters and Setters, 这个在上面实例变量里已经说过了. Dart会帮我们自动创建的. 这里唯一要提一下的是, 我们可以通过实现getters和setters来增加额外的成员. 举例如下.

c. Abstract methods, 抽象方法要用:来结尾. 注意, 抽象方法只能存在于抽象类中.

d. Overide Operators. 我们可以复写操作符. 个人觉得这个不太常用.

5: Others:
a. Abstract classes. 抽象类不可实体化. 如果我们实在需要实体化, 可以通过做个factory constructor. 个人认为这个也没啥必要. 因为通常情况下, 我们定义抽象类都是为了定义接口的.
b. 自带interfaces. 重要的事情戳三遍!!! 这里要注意了, 在Dart里, 每一个类是自带一个interface的. 如果我们想用一个类的方法, 但是又不想继承这个类的实现, 我们可以使用implement. 举例如下.

c. extend, 继承. 没啥可说的. 继承一个类用extend关键字. 访问父类用super关键字.

d. Enumerated types. 这里要注意的是, 枚举在Dart中是用index来标记位置. 在Kotlin里我们用的是original. 别的没啥可说的, 枚举加switch, 跟豆浆油条一样. 不过用习惯了Kotlin里的when, 不要太嫌弃Dart的switch.

e. Adding features to a class: mixins. 重要的事情戳三遍!!! 这个超级有用. 在Flutter里我们经常会用with某一个mixin. 像TickerProviderStateMixin.

e. Static. 静态变量和静态方法. 这里基本上Dart和Java一样. 没啥可说的. 要注意的是. 在Dart里, 静态变量只有在使用的时候才会被创建. 这个机制和Java完全不一样. 还有, Dart建议我们应该用top-level function来替代静态方法的使用.
好了, 今天就到这里了. 这一篇有些长, 主要是类和对象是我们每天编程必用的部分. 所以我们需要仔细扣下doc.
下一篇我们要去玩泛型.
欧了, 谢谢观赏, 大家加油!