在scala中 trait 可以认为是 Java中interface 跟abstract class 集中的混合体,JVM 8 中 特质可以包含具体方法跟抽象方法,自己理解下 如果一个特质中既有抽象方法又有具体方法时,别的类继承该特质时的背后流程。scala 中 可以允许特质的动态混入,
构建对象的同时如果混入多个特质,称之为叠加特质
object aiguigu {
def main(args: Array[String]): Unit = {
val t = new T with T3
t.myprint
println("="*15)
val t2 = new T with T4
t2 myprint
}
}
trait T1{
println("T1 is created")
def myprint = println("T1 is my print")
}
trait T2{
println("T2 is created")
def myprint = println("T2 is my print")
}
trait T3 extends T1 with T2 {
println("T3 is created")
override def myprint: Unit = super.myprint
}
trait T4 extends T2 with T1 {
println("T3 is created")
override def myprint: Unit = super.myprint
}
class T {}
结果如下:
T1 is created
T2 is created
T3 is created
T2 is my print
===============
T2 is created
T1 is created
T3 is created
T1 is my print
object aiguigu {
def main(args: Array[String]): Unit = {
val mysql = new MySQL4 with DB4 with File4
mysql.insert(100)
}
}
trait Operate4 {
println("Operate4")
def insert(id: Int)
}
trait Data4 extends Operate4 {
println("Data4")
def insert(id: Int): Unit = {
println("插入数据 = " + id)
}
}
trait DB4 extends Data4 {
println("DB4")
override def insert(id: Int): Unit = {
println("向数据库")
super.insert(id)
}
}
trait File4 extends Data4 {
println("File4")
override def insert(id: Int): Unit = {
println("向文件")
super.insert(id)
// super[Data4].insert(id)
}
}
class MySQL4{}
结果如下:
Operate4
Data4
DB4
File4
向文件
向数据库
插入数据 = 100
结果:
- trait 特质实例化的执行顺序是:从左到右
- trait 调用多个同名方法时执行顺序是:从右到左 , 如果特质中调用了super,并不是表示调用父特质的方法,而是向前(向左) 继续查找特质,如果找不到才会去父特质查找。
- 如果想要调用具体特质的方法 可以指定super[特质].xxx(...) 其中的泛型必须是该特质的直接超类类型。 比如 super[Data4].insert(id) 执行顺序如下
Operate4 Data4 DB4 File4 向文件 插入数据 = 100
object tiger {
def main(args: Array[String]): Unit = {
/*
构建类对象, 在混入特质时,该对象还没有创建
调用当前类的超类构造器
第一个特质的父特质构造器
第一个特质构造器
第二个特质构造器的父特质构造器, 如果已经执行过, 就不再执行
第二个特质构造器
.......重复 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....")}
class EE { println("E...")}
class FF extends EE with CC with DD { //先继承了 EE 类,然后再继承 CC 和 DD
println("F....")
}
class KK extends EE { // KK 直接继承了普通类 EE 构造匿名子类,可以理解成在混入特质时,对象已经创建了
println("K....")
}
分析两种方式对构造顺序的影响
第 1 种方式实际是构建类对象, 在混入特质时,该对象还没有创建。
第 2 种方式实际是构造匿名子类,可以理解成在混入特质时,对象已经创建了然后添加特质属性。