乐趣区

关于scala:Scala-特质Trait

特质 Trait

在 scala 中,有一个既相似 java 接口的又相似 java 抽象类的概念,叫做特质 Trait。
咱们能够把他当作接口来用,应用形式和 java 的接口相似,也能够把他当作抽象类应用,应用形式就和 java 的抽象类相似。然而不论用接口还是形象的形式,都是应用关键字 extends
接口的形式:

trait ScalaTrait {def printInfo(): Unit
}

class ScalaClass extends ScalaTrait {override def printInfo(): Unit = {println("ScalaClass")
  }
}

object ScalaClass {def main(args: Array[String]): Unit = {
    val scalaClass = new ScalaClass
    scalaClass.printInfo()}
}

抽象类的形式:

trait ScalaTrait2 {def printInfo(): Unit

  def printInfo2(): Unit = println("printInfo2")
}

class ScalaClass2 extends ScalaTrait2 {override def printInfo(): Unit = {println("ScalaClass2")
  }
}

object ScalaClass2 {def main(args: Array[String]): Unit = {
    val scalaClass = new ScalaClass2
    scalaClass.printInfo()
    scalaClass.printInfo2()}
}

多个 Trait 继承

抽象类是不能多继承的,然而 Trait 是能够多继承的,多个 Trait 间接用 with 关键字。
上面例子中,ScalaClass3 既有 ScalaTraitA01 的办法实现,也有 ScalaTraitA02 的办法实现。

trait ScalaTraitA01 {def printInfo01(): Unit
}

trait ScalaTraitA02 {def printInfo02(): Unit
}

class ScalaClass3 extends ScalaTraitA01 with ScalaTraitA02 {def printInfo01(): Unit = {println(s"printInfo01")
  }

  def printInfo02(): Unit = {println(s"printInfo02")
  }
}

object ScalaClass3 {def main(args: Array[String]): Unit = {
    val scalaClass = new ScalaClass3
    scalaClass.printInfo01()
    scalaClass.printInfo02()}
}

反复属性

比方继承的多个 Trait 都有某个属性,那调用的时候,就不晓得是调用哪个属性,此时就须要子类去重写这个值,比方 str 通过 override 重写定义为 ScalaClass4。

trait ScalaTraitB01 {
  val str: String = "strB01"

  def printInfo01(): Unit}

trait ScalaTraitB02 {
  val str: String = "strB02"

  def printInfo02(): Unit = println("printInfo02" + str)
}

class ScalaClass4 extends ScalaTraitB01 with ScalaTraitB02 {
  override val str: String = "ScalaClass4"

  override def printInfo01(): Unit = {println(str)
  }
}

object ScalaClass4 {def main(args: Array[String]): Unit = {
    val scalaClass = new ScalaClass4
    scalaClass.printInfo01()
    scalaClass.printInfo02()}
}

反复办法

ScalaTraitC01 和 ScalaTraitC02 都有 printInfo01 办法,子类调用 super.printInfo01(),结果显示调用的是 ScalaTraitC02 里的办法。
在 Trait 调用链中,是从 with 的最左边往左边调用。

trait ScalaTraitC01 {
  val str: String = "strC01"

  def printInfo01(): Unit = println("printInfoC01" + str)
}

trait ScalaTraitC02 {
  val str: String = "strC02"

  def printInfo01(): Unit = println("printInfoC02" + str)
}

class ScalaClass5 extends ScalaTraitC01 with ScalaTraitC02 {
  override val str: String = "ScalaClass5"

  override def printInfo01(): Unit = {super.printInfo01()
  }
}

object ScalaClass5 {def main(args: Array[String]): Unit = {
    val scalaClass = new ScalaClass5
    scalaClass.printInfo01()}
}

咱们能够通过这个个性实现责任链模式:

trait ScalaTraitD00 {def printInfo01(): Unit = {}}

trait ScalaTraitD01 extends ScalaTraitD00 {override def printInfo01(): Unit = {println("ScalaTraitD01")
    super.printInfo01()}
}

trait ScalaTraitD02 extends ScalaTraitD00 {override def printInfo01(): Unit = {println("ScalaTraitD02")
    super.printInfo01()}
}

trait ScalaTraitD03 extends ScalaTraitD00 {override def printInfo01(): Unit = {println("ScalaTraitD03")
    super.printInfo01()}
}

class ScalaClass6 extends ScalaTraitD01 with ScalaTraitD02 with ScalaTraitD03 {override def printInfo01(): Unit = {super.printInfo01()
  }
}

object ScalaClass6 {def main(args: Array[String]): Unit = {
    val scalaClass = new ScalaClass6
    scalaClass.printInfo01()}
}

打印后果如下:

ScalaTraitD03
ScalaTraitD02
ScalaTraitD01
退出移动版