Scala のトレイトは実装のある Java インターフェースのようなものです。トレイトはクラスにミックスインして使用します。ミックスインは継承のようなものです。コード上ではクラス定義時に extends や with でトレイトを指定します。Scala は Java と同様に親クラスは一つまでしか指定できません。一方でトレイトは Java インターフェースのようにいくつでもミックスインできます。これによって多重継承のような需要は満たせます。継承ではなくミックスインですので、ダイヤモンド継承のように異なるミックスイン経路が二重三重に存在していても問題になりません。
trait.scala
object Main {
def main(args: Array[String]) {
val obj = new MyClass
obj.myMethod
}
}
trait MyTrait {
def myMethod() {
println("MyTrait::myMethod()")
}
}
class MyClass extends MyTrait {
}
実行例
$ scalac trait.scala && scala Main
MyTrait::myMethod()
trait.scala
object Main {
def main(args: Array[String]) {
val obj = new MySubClass
obj.myMethod
}
}
trait MyTrait {
def myMethod() {
println("MyTrait::myMethod()")
}
}
class MyClass {
}
class MySubClass extends MyClass with MyTrait {
}
実行例
$ scalac trait.scala && scala Main
MyTrait::myMethod()
trait.scala
object Main {
def main(args: Array[String]) {
val obj = new MySubClass
obj.myMethod
obj.myMethod2
}
}
trait MyTrait {
def myMethod() {
println("MyTrait::myMethod()")
}
}
trait MyTrait2 {
def myMethod2() {
println("MyTrait2::myMethod()")
}
}
class MyClass {
}
class MySubClass extends MyClass with MyTrait with MyTrait2 {
}
実行例
$ scalac trait.scala && scala Main
MyTrait::myMethod()
MyTrait2::myMethod()
C++ オーバーライド (仮想関数とアップキャスト) で紹介したようなことが Scala でも実装できます。
trait.scala
object Main {
def main(args: Array[String]) {
val objA: MyTrait = myFunc('A')
val objB: MyTrait = myFunc('B')
val obj: MyTrait = myFunc('-')
objA.myMethod //=> MyClassA::myMethod()
objB.myMethod //=> MyClassB::myMethod()
obj.myMethod //=> MyTrait::myMethod()
}
def myFunc(arg: Char): MyTrait = {
arg match {
case 'A' => new MyClassA
case 'B' => new MyClassB
case _ => new MyClass
}
}
}
trait MyTrait {
def myMethod() {
println("MyTrait::myMethod()")
}
}
class MyClassA extends MyTrait {
override def myMethod() {
println("MyClassA::myMethod()")
}
}
class MyClassB extends MyTrait {
override def myMethod() {
println("MyClassB::myMethod()")
}
}
class MyClass extends MyTrait {
}
実行例
$ scalac trait.scala && scala Main
MyClassA::myMethod()
MyClassB::myMethod()
MyTrait::myMethod()