trait-多继承

47 阅读2分钟

(一)多继承构造器的执行顺序

  1. 先父 后子
  1. 如果有多个父类,则按照从左到右的顺序调用。

image.png

package level02

/*
特质
trait: 实现多继承
构造器的执行顺序
1、先父 后子
2、如果是多继承,有多个trait,按书写顺序从左到右
* */
object class12 {

  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也有自己的父类,要先执行父类构造器

image.png

package level02

/*
特质
trait: 实现多继承
构造器的执行顺序
1、先父 后子
2、如果是多继承,有多个trait,按书写顺序从左到右
* */
object class12 {

  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.....

image.png

(三)空指针异常

调用p.log()时,fileName没有值。这就是继承时带的问题:先执行了trait构造器的代码,后执行了具体子类的构造器。而具体的赋值操作是在子类的构造器中才进行,所以,父类的filename没有值,导致空指针异常。

问题解决

方法1:懒加载

lazy val fileout = new PrintWriter(filename)

方法2:提前定义

val p = new {override val filename="p052.log"} with Person051

详情请见 “ 代码改错(Lazy)

(四)trait与类的区别

相同点: 类和trait都可以定义成员变量(抽象,具体);继承时都使用extends关键字;

不同点: trait的构造器不能带参数;trait支持多继承;

package level02

import java.io.FileWriter

/*
  trait 和 class 的区别

  1. class 类。 伴生类,抽象类,内部类。 不能多继承。
  2. trait 特质。 可以多继承。构造器不能带参数。 extends  with

  共同点
  1. 都可以有:具体属性,抽象属性,具体方法,抽象方法
*/
object class14 {

  class A{}
  trait B{}

  class AB extends A with B{

  }

  def main(args: Array[String]): Unit = {

  }
}