2012年7月8日日曜日

[Scala] 実装付き trait の仕組み

前の記事で書いたように、Scala の trait には、
  • 実装を持つことができる。
  • クラスは(Java の Interface と同様に) 複数の trait を実装することができる。
という特徴があるので、多重継承みたいなことができてしまう。
(ちなみに、trait を実装することを Scala では ミックスイン というらしい。)

Scala は Java の上で動くわけなので Java でできないことはできないわけなのだが、どのように実現されているのだろうか?
例外を発生させてスタックトレースを見てみることにする。

まずは、普通にクラスを extends した場合。

object TraitSample {
    def main(args : Array[String]) {
        new English().hello();
    }
}

class Greetable {
  def hello() : String = {
    throw new IllegalArgumentException("in Greetable");
  }
}

class English() extends Greetable {
}

Exception in thread "main" java.lang.IllegalArgumentException: in Greetable at Greetable.hello(TraitSample.scala:9) at TraitSample$.main(TraitSample.scala:3) at TraitSample.main(TraitSample.scala)

普通に見慣れた感じのスタックトレース。スタック中に English.hello()は出現していない。

次に、trait を使ってみる。

object TraitSample {
    def main(args : Array[String]) {
        new English().hello();
    }
}

trait Greetable {
  def hello() : String = {
    throw new IllegalArgumentException("in Greetable");
  }
}

class English() extends AnyRef with Greetable {
}

Exception in thread "main" java.lang.IllegalArgumentException: in Greetable at Greetable$class.hello(TraitSample.scala:9) at English.hello(TraitSample.scala:13) at TraitSample$.main(TraitSample.scala:3) at TraitSample.main(TraitSample.scala)

ふむ。
このスタックトレースを見ると、まず実装クラスの English.hello() が実行されて、そこから、Greetable$class.helloというクラスが呼び出されていることがわかる。

つまり、実装クラスにメソッドが生成されるとともに 実装 trait のオブジェクトも生成されていて、 実装クラスのメソッドから実装 trait オブジェクトのメソッドが実行される、という構造になっているようだ。

0 件のコメント:

コメントを投稿