Scala のトレイトは実装のある Java インターフェースのようなものです。トレイトはクラスにミックスインして使用します。ミックスインは継承のようなものです。コード上ではクラス定義時に extends や with でトレイトを指定します。Scala は Java と同様に親クラスは一つまでしか指定できません。一方でトレイトは Java インターフェースのようにいくつでもミックスインできます。これによって多重継承のような需要は満たせます。継承ではなくミックスインですので、ダイヤモンド継承のように異なるミックスイン経路が二重三重に存在していても問題になりません。
サンプルコード
クラスからトレイトを extends で指定してミックスイン
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()
クラスにトレイトを with でミックスイン
一つのトレイトを指定
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()
関連記事
- Scala 文字列の処理書式指定 object Main { def main(args: Array[String]): Unit = { println("%d + %d = %d".format(1, 1, 2)) //=> 1 + 1 = 2 } } 文字列の比較 ヒアドキュメント 他の言語でいう「ヒアドキュメント」のようなものは """ で囲うことで実現できます。 object Main ...
- Scala 日付に関する処理Date クラスを文字列にフォーマット import java.util.Date object Main { def main(args: Array[String]): Unit = { // format は Date に限らない文字列用の機能です。 println("%d-%d-%d" format (1, 1, 1)) //=> 1-1-1 printl...
- 酢豚の基本的な使い方 (sbt)sbt は Scala および Java を主な対象としたビルドツールです。Scala Build Tool の略ではありませんが、Simple Build Tool という明示的な記述も公式ドキュメントなどには見当りません。以下 sbt の基本的な使用例をまとめます。使用した sbt のバージョンは 0.13 です。 公式ドキュメント [sbt 0.13](http://www.scala-sb...
- Scala 関数のサンプルコード「デフォルト引数」および「Unit 型を返す関数」 object HelloWorld { def main(args: Array[String]): Unit = { def myPrint(myArg: String = "default_value") = println(myArg + "!") val result = myPrint() //=> defau...
- Scala 組み込みの制御構造if-else 条件分岐で知られる if-else は三項演算子のようにも使用されます。 object HelloWorld { def main(args: Array[String]): Unit = { val myVal = if (!args.isEmpty) args(0) else "default" println(myVal) } ...