Xtendを触ってみる その5 ディスパッチメソッド

今日は拡張メソッドと並ぶXtendの目玉機能の1つであるディスパッチメソッドについてです。
ディスパッチメソッドとは、CLOSなどの総称関数(Generic Function)をメッセージ伝達モデルのオブジェクト指向言語に持ってきたような機能で、同じ名前のメソッドを引数の型によって呼び分けることができるというものです。
CLOSの総称関数は普通に関数呼び出しとして呼び出すわけですが、Xtendのディスパッチメソッドは拡張メソッドの記法を使用して第一引数の型のオブジェクトをレシーバとして呼び出すことができます。
ディスパッチメソッドはdispatchキーワードをつけて定義します。

def dispatch println(Person person){
  println('''name=≪person.name≫, mail=≪person.mail≫''')
}

def dispatch println(Object obj){
  println(obj.toString)
}

呼び出すときは拡張メソッドと同じでこんな感じになります。

val s = "Hello World"
a.println()

val p = new Person("Naoki Takezoe", "takezoe@gmail.com")
p.println()

ディスパッチメソッドは以下のようなJavaコードに変換されます。型に応じたメソッドにディスパッチされていることがわかります。

public Object println(final Object person) {
  if (person instanceof Person) {
    return _println((Person)person);
  } else {
    return _println(person);
  }
}

引数が複数の場合はどうなるでしょうか?

def dispatch println(Person person, String arg){
  ...
}

def dispatch println(Object obj, int arg){
  ...
}

def dispatch println(Object obj, Object arg){
  ...
}

生成されるJavaコードは以下の通りです。ちゃんとすべての引数に対して型のチェックが行われて適切なメソッドにディスパッチされています。

public Object println(final Object person, final Object arg) {
  if ((person instanceof Person)
       && (arg instanceof String)) {
    return _println((Person)person, (String)arg);
  } else if (arg instanceof Integer) {
    return _println(person, (Integer)arg);
  } else {
    return _println(person, arg);
  }
}

Xtendは一見すると「Javaの機能を絞り込んで、記述を簡単にするためのシンタックスシュガーと関数型言語の機能の一部を取り込んだ言語」のように見えますが、実は「メッセージ伝達モデルと総称関数モデルのハイブリッド型オブジェクト指向言語」といえるのではないでしょうか。少し触れただけではいかにも中途半端な言語のように感じますが、そう考えるとなかなか興味深い試みのように思えます。
さて、これでXtendの言語としての特徴的な部分については一通り触れたかなと思いますが、次回はXtendに標準で用意されているライブラリについて紹介したいと思います。というわけでもう少しだけ続きます。