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....")
}
原文地址:https://www.cnblogs.com/yangxusun9/p/12775396.html