0%

scala特质

scala特质(特征)

在java中是存在接口interface的,而scala中使用特质trait来代替接口,多个类具有相同的特质时,就可以将这个特质独立出来,采用关键字 trait声明。 理解trait 等价于(interface + abstract class)

语法

1
2
3
trait 特证名 {
trait
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 定义特质
trait Breathable{
def breath()
}

trait Flyable{
def fly()
}

trait Swimmable{
def swig()
}

// 没有父类,直接继承特质
// class 类名 extends 特质
// 如果同时继承多个特质的话需要使用with class 类名 extends 特质1 with 特质2 with 特质3
class Animal extends Breathable {
var name: String = "动物"

def sayHello: Unit = {
println("你好,我是" + name)
}

override def breath(): Unit = {
println("我会呼吸")
}
}

// 有父类,需要先继承父类,再继承特质
// class 类名 extends 父类 with 特质1 with 特质2 with 特质3
class Bird extends Animal with Flyable{
override def fly(): Unit = {
println("我会飞")
}
}

class Dog extends Animal with Swimmable{
override def swig(): Unit = {

println("我会狗刨")
}
}


  • scala的特质中可以包含抽象方法,也可以包含具体方法
  • 特质中如果存在字段,则初始化了就是具体字段,没有初始化则为抽象字段
  • 特质可以继承类来扩展该特质的功能
  • 重写特质的抽象方法时不需要加override关键字
  • 同时继承多个特质的话使用with,class 类名 extends 父类 with 特质1 with 特质2 with 特质3

富接口表示在特质中既有抽象方法又有非抽象方法

scala动态混入

除了可以在类声明时继承特质以外,还可以在构建对象时混入特质,扩展目标类的功能,使用with可以动态的混入特质

1
2
3
4
5
6
7
8
9
10
11
class Seal{

}

// 动态混入
val seal = new Seal with Swimmable {
override def swig(): Unit = {
println("我会游泳哦")
}
}
seal.swig()

如果同时混入多个特质,这种情况称为叠加特质,加载的顺序是从左到右

1
2
3
4
5
6
7
8
9
10
11
var seal2 = new Seal with Swimmable with Breathable{
override def swig(): Unit = {
println("我会游泳啊")

}

override def breath(): Unit = {

println("我会呼吸啊")
}
}

如果在叠加特质的方法中包含有super调用,会首先向左边继续查找特质,如果找不到才会去父特质查找,如果想要调用具体特质的方法,可以指定:super[特质].xxx(…).其中的泛型必须是该特质的直接超类类型

构造顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
object TestTrait {
def main(args: Array[String]): Unit = {
//E
//A
//B
//C
//D
//F
val f = new F
}
}

trait A{
println("A")
}

trait B extends A{
println("B")
}

trait C extends B{
println("C")
}

trait D extends C{
println("D")
}

trait E {
println("E")
}

class F extends E with C with D{
println("F")
}
  • 调用当前类的超类构造器
  • 特质的顺序是从左到右的顺序
  • 第一个特质的父特质构造器
  • 第一个特质构造器
  • 第二个特质构造器的父特质构造器,如果已经执行过, 就不再执行
  • 第二个特质构造器
  • …….重复4,5的步骤(如果有第3个,第4个特质)
  • 当前类构造器

欢迎关注我的其它发布渠道