多个trait的加载顺序
如果有多个父类,则按照从左到右的顺序调用
代码示例:
/*
trait:实现多继承
trait多继承构造器的执行顺序
1、先父,后子
2.如果是多继承,有多个trait,按书写顺序从左到右
*/
object day32 {
trait A {
println("A特质构造器")
}
trait B {
println("B特质构造器")
}
trait C {
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()
}
}
运行结果:
C特质构造器
B特质构造器
A特质构造器
child...
多层trait的加载顺序
先执行父类中的构造器,再执行子类的构造器:如果trait也有自己的父类,要先执行父类构造器
代码示例:
object day33 {
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...
空指针异常
以上报错原因就是空指针异常
解决方法:
方法1.懒加载
import java.io.FileWriter
object day34 {
trait FileLogger {
println("fileLogger")
val filename:String
//懒加载效果
//这个对象不会立刻去创建,而是等你需要使用的时候才去创建
lazy val writer=new FileWriter(filename)
def writerLog(msg:String)={
writer.write(msg)
writer.close()
}
}
class MyWriter extends FileLogger{
println("MyWriter")
override val filename:String="test.log"
}
def main(args: Array[String]): Unit = {
val log=new MyWriter()
log.writerLog("测试内容")
}
}
方法2.提前定义
import java.io.FileWriter
object day34 {
trait FileLogger {
val filename: String
val writer = new FileWriter(filename)
// 写入日志方法
def writeLog(msg: String): Unit = {
writer.write(msg)
writer.close()
}
}
// 子类:用【提前定义】解决初始化顺序问题
class MyWriter extends {
// 提前定义:在父特质初始化前,先给filename赋值
// 作用:让FileLogger创建writer时,filename已经有值(不是null),避免NPE
override val filename: String = "test.log"
} with FileLogger // 继承FileLogger特质
def main(args: Array[String]): Unit = {
val log = new MyWriter()
log.writeLog("测试内容")
}
}
报错解决完,运行后会生成一个"test.log"的文件
trait与类class的区别
相同点:
- 类和
trait都可以定义成员变量(抽象,具体); - 继承时都使用
extends关键字;
不同点:
trait的构造器不能带参数;trait支持多继承;
/*
trait和class的区别
1.class类 伴生类,抽象类,内部类,不能多继承
2.trait特质 可以多继承·,构造器不能带参数 extends with
共同点
1.都可以有:具体属性,抽象属性,具体方法,抽象方法
2.都使用extends来做继承
*/
object day35 {
class A{}
trait B{}
class AB extends A with B{
}
def main(args: Array[String]): Unit = {
}
}