Scala trait 特质

30 阅读2分钟

trait

  • 特质:  trait
  • trait是关键字,identified 表示一个合法的标记。
  • 作用:  类似于抽象类 定义抽象属性 方法
  • 让其他的子类去实现
  • 特点:可以实现多继承
  • 作用:  封装成员和方法,供其他类来实现。它可以实现多继承!

一、实现单个特质

用一个类去实现单个特质

trait A {
  var name:String;
}

class Class1 extends A {
  var name:String = "Class1"
}

def main(args: Array[String]): Unit = {
  val class1 = new Class1()
  println(class1.name)
}

二、实现多个特质

类名 extends 特质1 with 特质2 with 特质3  其中多个特质的顺序可以交换。

trait A {
  var name:String;  // __抽象__属性
  def sayA():Unit = {  // __具体__方法
    println("sayA")
  }
}
trait  B {
  var age:Int
}

class Class1 extends A with B {
  var name:String = "Class1"
  var age:Int = 4
}

def main(args: Array[String]): Unit = {
  val class1 = new Class1()
  class1.sayA
  println(class1.name)
  println(class1.age)
}

三、多继承

① 有多个父类,从左到右的顺序去调用构造器

问:  一个类实现了多个特质之后,所涉及的多个构造器的执行顺序如何确定?

答:  如果有多个父类,则按照从左到右的顺序调用。

trait A {
  println("trait A")
}
trait  B {
  println("trait B")
}
trait  C {
  println("trait C")
}

class Class1 extends B with A with C{
  println("class 1.....")
}

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

② 先父后子。  先调用父类构造器,再调用子类构造器

先执行父类中的构造器,再执行子类的构造器:如果trait1也有自己的父类,要先执行父类构造器

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 B with A with C{
  println("class 1.....")
}

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

四、class 与 trait 的区别

1. 相同点

  • 可以被继承,extends
  • 属性和方法:抽象属性,具体属性,抽象方法
  • 都不能被实例化,不能new

2.不同点

  • trait 支持多继承;抽象类不能多继承
trait A {
  println("trait A")
}

trait  B {
  println("trait B")
}

class C extends A with B{

}

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

五、空指针异常

**目标:**实现日志类 可以把一些文本信息写入指定的文件中

trait Log {
  // 文件名:抽象属性
  var fileName:String

  // 具体属性
  // lazy 懒加载 懒
  // 将 fileWriter 改为 lazy val 或 def,确保在 fileName 初始化后使用
  lazy val fileWriter:FileWriter = new FileWriter(fileName)

  def writeLog(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.writeLog("2025-11-19; 下午 天气晴朗")
}