Scala中trait基本使用

48 阅读2分钟

(一) trait的定义与作用

Scala没有Java中接口的概念,所以Scala的trait就类比Java中的接口

trait是关键字,identified 表示一个合法的标记。

 作用:封装成员和方法,供其他类来实现。它可以实现多继承!

(二)实现单个特质

package levelo3

object class010 {
 trait A {
   var name:String;
   def sayA():Unit={
     println("sayA")
   }
 }
 class Class1 extends A {
   var name:String="Class1"

 }

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

(三) 实现多个特质

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

package levelo3

object class010 {
  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)
  }
}

多继承讲解

多继承时,构造器调用顺序
  1. 先父后子。先调用父类构造器,在调用子类构造器
  2. 有多个父类,从左到右的顺序去调用构造器

代码演示:

package levelo3

object class010 {
  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)
  }
}

结果:

image.png

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

object class011 {
  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()
  }
}

结果:

image.png

空指针异常

问题解决方法

方法1:懒加载

lazy val fileout = new PrintWriter(filename)

方法2:提前定义

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

trait与类的区别

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

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


package levelo3

import java.io.FileWriter

object class012 {
  trait Log {
    var fileName:String
    println(s"${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:下午,天气晴朗")
  }
}

结果:

image.png