特质(trait)
trait : 实现多继承。
(一)多个trait的加载顺序
1.先父 后子。
2.如果是多继承,有多个trait, 按书写顺序从左到右。
3.如果有多个父类,则按照从左到右的顺序调用。
object f1118 {
trait A {
println("A特质构造器")
}
trait B {
println("B特质构造器")
}
trait C {
println("C特质构造器")
}
class Child extends A with B with C{
println("child...")
} //继承 三个特质A B C
def main(args: Array[String]): Unit = {
val child = new Child()
}
//运行结果:
A特质构造器
B特质构造器
C特质构造器
child...
(二)多层trait的加载顺序
先执行父类中的构造器,再执行子类的构造器:如果trait1也有自己的父类,要先执行父类构造器。
object f1118 {
trait AA {
println("AA 特质构造器")
}
trait A extends AA {
println("A 构造器")
}
trait B {
println("B特质构造器")
}
trait CC {
println("CC特质构造器")
}
trait C extends CC{
println("C 构造器")
}
class Child extends C with B with A{
println("child...")
} //继承 三个特质A B C
def main(args: Array[String]): Unit = {
val child = new Child()
}
//运行结果:
CC特质构造器
C 构造器
B特质构造器
AA 特质构造器
A 构造器
child...
(三)空指针异常
object a1118 {
trait FileLoogger {
val filename:String
val writer = new FileWriter(filename)
def writeLog(msg:String) = {
writer.write(msg)
writer.close()
}
}
class MyWriter extends FileLoogger{
override val filename: String = "test.log"
}
def main(args: Array[String]): Unit = {
val log = new MyWriter()
log.writeLog("测试内容")
}
//运行结果:
会报错
报错原因: 调用p.log()时,fileName没有值。这就是继承时带的问题:先执行了trait构造器的代码,后执行了具体子类的构造器。而具体的赋值操作是在子类的构造器中才进行,所以,父类的filename没有值,导致空指针异常。
问题解决
方法1:懒加载
lazy val fileout = new PrintWriter(filename)
方法2:提前定义
val p = new {override val filename="p052.log"} with Person051
正确代码如下:
object a1118 {
trait FileLoogger {
val filename:String
//懒加载效果
//这个对象不会立刻去创建 而是等到你需要使用的时候才去创建
lazy val writer = new FileWriter(filename)
def writeLog(msg:String) = {
writer.write(msg)
writer.close()
}
}
class MyWriter extends FileLoogger{
override val filename: String = "test.log"
}
def main(args: Array[String]): Unit = {
val log = new MyWriter()
log.writeLog("测试内容")
}
运行成功结果如下:
(四)trait与类的区别
-
相同点:类和trait都可以定义成员变量(抽象,具体);继承时都使用
extends关键字; -
不同点:
trait的构造器不能带参数;trait支持多继承;
trait 和 class 的区别:
1.class类 伴生类 抽象类 内部类 不能多继承
2.trait特质 可以多继承 构造器不能带参数 关键字:extends with
共同点:
1.都可以有 具体属性 抽象属性 具体方法 抽象方法
2.都使用extends来做继承