特质与类基本类似,Trait是字段和行为的集合。
下面来介绍一下特质的构成特点
1.字段
(1)特质的字段可以是抽象的也可以是具体的(有具体的值)。
(2)特质的每一个字段,使用该特质的类都会获得一个字段与之对应,从特质继承来的字段被直接加入到子类中。
(3)特质中的抽象字段在具体子类中必须被重写,不需要写override。
2.特质的构造顺序(重要)
(1)首先调用超类构造器
(2)然后特质构造器(在超类构造器和子类构造器之间)
①每个特质的父特质先被构造
②多个特质共有一个父特质的时候,父特质只构造一次
(3)构造子类
注:特质的构造顺序从左向右(与线性化的顺序相反)
3.类的线性化(为类规定执行顺序)
混入的顺序决定行为
越靠近右侧的特质先起作用。
当你调用带混入的类的方法时,最右侧特质的方法首先被调用。如果这个方法调用了super,它调用其左侧的特质方法。(后面小例子会有演示)
4.sealed关键字
用sealed关键字可以让编译器检查模式匹配的时候检查你的代码中有没有漏掉一些case情况,减少编程错误。
5.特质也可以扩展类
特质继承了类1,当类2继承此特质时,类1自动成为类2的超类
6.特质的例子:
父特质 ArrayOperator
import scala.collection.mutable.ArrayBuffer
trait ArrayOperator {
println("构造父特质Operator")
def operator(arr: ArrayBuffer[Int]): ArrayBuffer[Int] = {
arr
}
}
子特质1 Doubling 作用:将列表内每个数*2
import scala.collection.mutable.ArrayBuffer
trait Doubling extends ArrayOperator{
println("构造1.Doubling trait")
override def operator(arr:ArrayBuffer[Int]):ArrayBuffer[Int]={
val length=arr.size
for (_<-0 until length){
val in=arr(0)*2
arr.remove(0)
arr+=in
print(in+" ")
}
println()
println("执行特质1.Operator:Doubling")
super.operator(arr)
arr
}
}
子特质2 Incrementing 作用:将列表内每个数+1
import scala.collection.mutable.ArrayBuffer
trait Incrementing extends ArrayOperator{
println("构造2.Incrementing trait")
override def operator(arr:ArrayBuffer[Int]):ArrayBuffer[Int] ={
val length=arr.size
for (_<-0 until length){
val in=arr(0)+1
arr.remove(0)
arr+=in
print(in+" ")
}
println()
println("执行特质2.Operator:Incrementing")
super.operator(arr)
arr
}
}
子特质3 FilterNegtive 作用:过滤掉列表里的负数
import scala.collection.mutable.ArrayBuffer
trait FilterNegtive extends ArrayOperator {
println("构造3.FilterNegtive trait")
override def operator(arr:ArrayBuffer[Int]):ArrayBuffer[Int] ={
val length=arr.size
for(_ <-0 until length){//用队列思想实现整数队列操作
val in=arr(0)
arr.remove(0)
if (in>0){
arr+=in
print(in+" ")
}
}
println()
println("执行特质3.Operator:FilterNegtive")
super.operator(arr)
arr
}
}
类 IntarrayOperator 注意看特质的继承顺序
class IntarrayOperator extends Doubling with Incrementing with FilterNegtive {
}
测试:
import scala.collection.mutable.ArrayBuffer
object testArray {
def main(args: Array[String]): Unit = {
val arroperator=new IntarrayOperator
val arr=ArrayBuffer[Int]()
arr+=(1,2,3,4,5,-9,15)
arroperator.operator(arr)
//arroperator.increment(arr,15)
}
}
测试结果:(特质的构造顺序和方法执行顺序对比可以看到,两者是相反的)
总结:在这里使用了在子特质中调用了super,可以把构造顺序和执行顺序都表现出来
如果没有调用super,如果三个特质都重写了父特质的方法,则只执行最右侧特质定义的方法(线性化)