一、Trait基础
-
将Trait作为接口使用
(1) 与Java的接口Interface相似。(2) 但Scala中没有implements关键字,无论继承class还是trait,统一使用关键字extends
(3) Scala不支持对class的多重继承,但支持对trait的多重继承。从第二个trait开始需要使用关键字with
-
在Trait中定义具体方法
(1) Trait中还可以定义具体方法,更像是包含了通用工具方法的东西
(2) “Trait的功能混入了类定义”
-
在Trait中定义具体字段
Trait可以定义具体field,此时继承trait的class就自动获得了trait中定义的field。但这与继承class是不同的:前者直接被添加到类中,追加定义;后者子类field只是父类field的引用
-
在Trait中定义抽象字段
(1) Trait可以定义抽象field,具体方法也可以基于抽象field来编写
(2) 继承Trait的类,则必须覆盖抽象field,提供具体的值
二、Trait高级
-
为单实例对象混入Trait(创建时混入)
在new时使用with指定
-
Trait调用链(职责链模式)
(1) Scala支持让class继承多个trait后,依次调用多个Trait的同一个方法。只要在多个Trait的同一个方法中,在最后都执行super.xxx()即可
(2) 从最右边的Trait方法开始执行,然后依次往左执行
-
Trait中覆盖抽象方法
(1) 子Trait可以覆盖父Trait的抽象方法。
子Trait可以覆盖父Trait的抽象方法。但覆盖时,若使用super.xxx()【抽象方法】,则无法通过编译。因为super.xxx()会去调用父Trait的xxx抽象方法,此时子Trait的方法还会被认为时抽象的
(2) 通过编译的解决办法:给子trait的方法加上abstract override修饰
-
混合使用Trait的具体方法和抽象方法(模板方法模式)
-
Trait的构造机制
(1) Trait有其构造代码,即那些不包含在任何方法中的代码(2) 继承了Trait的class构造规则
[1] 父类的构造器执行[2] Trait的构造代码执行,多个Trait从左到右依次执行。构造Trait时会先构造父Trait,如果多个Trait继承自统一父Trait,则父Trait只会构造一次
[3] 所有Trait构造完毕之后,子类的构造器执行
-
Trait字段的初始化
(1) 按照构造规则,Trait将在class之前被构造,若没有对字段进行初始化就在Trait构造代码中使用,会引发NullPointer异常(2) 解决方案:提前定义
[1]方式一:
[2]方式二: