(一)多个trait的加载顺序
如果有多个父类,则按照从左到右的顺序调用
package level02
object class08 {
/* 特质
* trait: 实现多继承(混入多个特质)
* 构造器的执行顺序
*1, 先父 后子
* 如果是多继承,有多个trait ,按照写顺序从左到右
*/
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()
}
}
(二)多层trait的加载顺序
先执行父类中的构造器,再执行子类的构造器:如果trait1也有自己的父类,要先执行父类构造器
package level02
object class08 {
/* 特质
* trait: 实现多继承(混入多个特质)
* 构造器的执行顺序
*1, 先父 后子
* 如果是多继承,有多个trait ,按照写顺序从左到右
*/
trait AA {
println("AA 特质构造器 ")
}
trait A extends AA {}
println("A 构造器")
trait B {
println("B 特质构造器 ")
}
trait CC{
println("C 特质构造器 ")
}
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()
}
}
(三) 空指针异常
object class18 {
trait FileLogger {
println("fileLogger")
val filename: String
// 延迟初始化writer,确保filename已被子类初始化
lazy val writer = new FileWriter(filename)
def writeLog(msg: String): Unit = {
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.writeLog("测试内容")
}
}
问题分析:通过打印,引导学生找到问题:调用p.log()时,fileName没有值。这就是继承时带的问题:先执行了trait构造器的代码,后执行了具体子类的构造器。而具体的赋值操作是在子类的构造器中才进行,所以,父类的filename没有值,导致空指针异常
代码定义了一个特质FileLogger,其中包含一个抽象字段filename、一个延迟初始化的FileWriter对象writer以及一个用于写入日志的方法writeLog;还定义了一个类MyWriter继承自FileLogger并实现了filename字段,最后有一个main方法用于测试。
package level02
object class08 {
/*
*
*/
trait FileLogger{
println("fileLogger")
val filename:String
// 懒加载效果
// 这个对象不会立刻去创建,而是等到你需要使用的时候才去创建
lazy val writer = new FileWriter(filename)
def writeLog(msg : String): Unit = {
writer.write(msg)
writer.close()
}
}
class MyWriter extends FileLogger {
println("MyWriter")
override val filename: String = "test1.log"
}// 继承 三个特质A,B,C
def main(args: Array[String]): Unit = {
val log = new MyWriter()
log.writeLog("测试内容")
}
}
总结
- trair 和 class 的区别
-
- class 类 伴生类 ,抽象类 ,内部类 。不能多继承
-
- trait 特质。 可以多继承 构造器不能带参数 extends with
- 共同点
- 都可以有 :具体属性,具体方法,抽象方法
- 都使用extends来做继承
- 完结撒花 !!!!!!!!!!
- 制作不易 希望·一键三连 在此感谢关注的粉丝宝宝
- 新来的宝宝可以关注下主播哟!!!!!