7

Scala - 特质Trait

 3 years ago
source link: https://segmentfault.com/a/1190000039984151
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

特质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

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK