Scala 关于叠加特性的理解
代码示例
package com.atguigu.chapter08.mixin //看看混入多个特质的特点(叠加特质) object AddTraits { def main(args: Array[String]): Unit = { val mysql = new MySQL4 with DB4 with File4 println(mysql) mysql.insert(100) println("===================================================") } } trait Operate4 { //特点 println("Operate4...") def insert(id: Int) //抽象方法 } trait Data4 extends Operate4 { //特质,继承了Operate4 println("Data4") override def insert(id: Int): Unit = { //实现/重写 Operate4 的insert println("插入数据 = " + id) } } trait DB4 extends Data4 { //特质,继承 Data4 println("DB4") override def insert(id: Int): Unit = { // 重写 Data4 的insert println("向数据库") super.insert(id) } } trait File4 extends Data4 { //特质,继承 Data4 println("File4") override def insert(id: Int): Unit = { // 重写 Data4 的insert println("向文件") super.insert(id) //调用了insert方法(难点),这里super在动态混入时,不一定是父类 //如果我们希望直接调用Data4的insert方法,可以指定,如下 //说明:super[?] ?的类型,必须是当前的特质的直接父特质(超类) // super[Data4].insert(id) } } class MySQL4 {} //普通类
关系图
问题
在构建对象时,它的构建顺序是
Scala在叠加特质的时候,会从左到右依次构建:
构建完MySQL4之后开始构建DB4==》DB4的父特质是Data4,所以会先构建Data4 ==》Data4 的父特质是Operate4,所以先构建Operate4 ==》所有父类构建完成之后,DB4开始完成自己的构造==》
开始构造FIle4时,依然还是会先找父类构造,但因为父类之前已经被构造过,所以就跳过,直接构造自己
所以输出为
1.Operate4...
2.Data4
3.DB4
4.File4
当我们执行一个动态混入对象的方法,其执行顺序是怎样的
顺序是,(1)从右到左开始执行 , (2)当执行到super时,是指的左边的特质 (3) 如果左边没有特质了,则super就是父特质
所以输出为:
1. 向文件"
2. 向数据库
3. 插入数据 100
以为这就完了吗?
补充
动态混入 和 常规混入 在构建时的一个细微差别:
动态混入会先把对象创建好在构建特质,而常规混入是先 构建父类,然后再构建特质,最后再是构建对象
object MixInSeq { def main(args: Array[String]): Unit = { //这时FF是这样 形式 class FF extends EE with CC with DD /* 调用当前类的超类构造器 第一个特质的父特质构造器 第一个特质构造器 第二个特质构造器的父特质构造器, 如果已经执行过,就不再执行 第二个特质构造器 .......重复4,5的步骤(如果有第3个,第4个特质) 当前类构造器 [案例演示] */ //1. E... //2. A... //3. B.... //4. C.... //5. D.... //6. F.... val ff1 = new FF() println(ff1) //这时我们是动态混入 /* 先创建 new KK 对象,然后再混入其它特质 调用当前类的超类构造器 当前类构造器 第一个特质构造器的父特质构造器 第一个特质构造器. 第二个特质构造器的父特质构造器, 如果已经执行过,就不再执行 第二个特质构造器 .......重复5,6的步骤(如果有第3个,第4个特质) 当前类构造器 [案例演示] */ //1. E... //2. K.... //3. A... //4. B //5. C //6. D println("=======================") val ff2 = new KK with CC with DD println(ff2) } } trait AA { println("A...") } trait BB extends AA { println("B....") } trait CC extends BB { println("C....") } trait DD extends BB { println("D....") }