在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