特质:trait
一.父子类的构造器执行顺序(多继承)
- 先父后子
- 有多个父类,按书写顺序从左向右执行
trait A {
println("A")
}
trait B {
println("8")
}
class Class1 extends A with B {
println("Class1")
}
def main(args: Array[String]): Unit = {
new Class1()
}
输出:
- 当给其中一段代码B增加一个父类
trait A {
println("A")
}
trait BB {
println("BB")
}
trait B extends BB{
println("8")
}
class Class1 extends B with A {
println("Class1")
}
def main(args: Array[String]): Unit = {
new Class1()
}
}
输出:
二.空指针异常
- 懒加载
lazy val fileout = new PrintWriter(filename)
- 提前定义
val p = new {override val filename="p052.log"} with Person051
用lazy延迟初始化fileWriter,确保filename在使用前已被初始化。
trait FileLogger {
println(2)
// 抽象字段,由子类实现
val filename: String
// 延迟初始化fileWriter,确保filename赋值后再创建
lazy val fileWriter = new FileWriter(filename, true)
def writeLog(msg: String): Unit = {
fileWriter.write(msg) // 加换行符方便查看
fileWriter.close()
}
}
class MyFileLogger extends FileLogger {
println(1)
// 子类实现filename
val filename = "11-26.log"
}
def main(args: Array[String]): Unit = {
val fileLogger = new MyFileLogger()
fileLogger.writeLog("今天上午上scala课程")
}
}
三.trait与抽象类的区别
- 相同点:类和trait都可以定义成员变量(抽象,具体);继承时都使用extends关键字;
- 不同点:trait的构造器不能带参数;trait支持多继承;