多个trait的加载顺序
有多个父类,则按照从左到右的顺序调用。
/*
* 多继承时,构造器调用顺序
* 1. 先父后子。先调用父类构造器,再调用子类构造器
* 2. 有多个父类,从左到右的顺手去调用构造器
* */
object class21 {
trait A {
println("trait A")
}
trait B {
println("trait B")
}
trait C {
println("trait C")
}
class Class1 extends A with B with C{
println("class 1...")
}
def main(args: Array[String]): Unit = {
new Class1()
}
}
多层trait的加载顺序
先执行父类中的构造器,再执行子类的构造器:如果trait1也有自己的父类,要先执行父类构造器
/*
* 多继承时,构造器调用顺序
* 1. 先父后子。先调用父类构造器,再调用子类构造器
* 2. 有多个父类,从左到右的顺手去调用构造器
* */
object class21 {
trait A {
println("trait A")
}
trait BB {
println("trait BB")
}
trait B extends BB {
println("trait B")
}
trait CC {
println("trait CC")
}
trait C extends CC {
println("trait C")
}
class Class1 extends A with B with C{
println("class 1...")
}
def main(args: Array[String]): Unit = {
new Class1()
}
}
输出结果:
trait A
trait BB
trait B
trait CC
trait C
class 1...
trait和class区别
- 相同点。
- 可以被继承,extends
- 属性和方法:抽象属性,具体属性,抽象方法,具体方法
- 都不能被实例化。不能new
- 不同点
- trait 支持多继承; 抽象类不能多继承
object class23 {
trait A {
println("trait A")
}
trait B {
println("trait B")
}
class C extends A with B {
}
def main(args: Array[String]): Unit = {
new C()
}
}
空指针异常
懒加载
import java.io.FileWriter
/*
* 空指针异常
*
* 目标:实现日志类,可以把一些文本信息写入指定的文件中
*
* */
object class24 {
trait Log {
// 抽象属性:文件名,
var fileName:String
println(s"${fileName}")
// 具体属性
// lazy 懒加载,懒
lazy val fileWriter:FileWriter = new FileWriter(fileName)
def writerLog(msg:String): Unit = {
fileWriter.write(msg)
fileWriter.close()
}
}
// 先执行父类构造器,所以报错
class TextLog extends Log {
var fileName:String = "text01.log"
}
def main(args: Array[String]): Unit = {
val textLog = new TextLog()
textLog.writerLog("2025-11-19: 下午,天气晴朗")
}
}