在scala中,有一個既相似java接口的又相似java抽象類的概念,叫作特質Trait。
咱們能夠把他看成接口來用,使用方式和java的接口相似,也能夠把他看成抽象類使用,使用方式就和java的抽象類相似。可是無論用接口仍是抽象的方式,都是使用關鍵字extends
。
接口的方式:java
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() } }
抽象類的方式:ide
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直接用with關鍵字。
下面例子中,ScalaClass3 既有ScalaTraitA01的方法實現,也有ScalaTraitA02的方法實現。scala
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。code
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() } }
打印結果以下:it
ScalaTraitD03 ScalaTraitD02 ScalaTraitD01