trait

traitの宣言と利用

trait は、Javaで言うインターフェースのようなものですが、メソッドのボディを持つことができる点が大きな違いとなります。
trait は以下のように定義します。

trait Friendly {
  def greet() = "Hi"
}

この例では、greet メソッドは"Hi"というString型の文字列を返却します。最後に評価された式の"Hi"が返却されるためです。


traitのミックスインにはextendsキーワードかwithキーワード(1つ目にはextends、それ以降はwith)を使います。Scalaではimplements はキーワードではありません。
そして、クラスはtraitをいくつでも実装できます。

class Dog extends Friendly {
  override def greet() = "Woof"
}

この例では、DogはtraitであるFriendlyを拡張しています。この継承関係は、Javaでのインターフェースの実装と同じことになります。このときoverrideキーワードを書かないとコンパイルできません。


Dogクラスを使うには、以下のようにします。

var pet: Friendly = new Dog
println(pet.greet())

Dogのインスタンスは、Friendly型として扱うことができるようになります。

ミックスイン

traitはインスタンス化時にミックスインできます。
以下の例では、Dogのインスタンス化時にExclamatoryGreeterの実装を追加しています。

trait Friendly { def greet() = "Hi" }

class Dog extends Friendly {
  override def greet() = "Woof"
}

trait ExclamatoryGreeter extends Friendly {
  override def greet() = super.greet() + "!!!"
}

object Example015 extends Application {
  val pup: Friendly = new Dog with ExclamatoryGreeter
  println(pup.greet())  //Woof!!!
}

上記例ではDogとExclamatoryGreeterの合成型が作られ、"Woof!!!" と表示されます!!