ダックタイピング

Think IT の記事を参考に、Scala でのダックタイピングを試してみた。
http://www.thinkit.co.jp/cert/article/0711/4/3/3.htm

object Sample {
  def foo[T](x: T {def bar: Boolean}): Boolean = x.bar
  def main(args: Array[String]): Unit = {
    println(foo(new { def bar = true }))
  }
}

ちゃんとコンパイル&実行できた。

foo の引数に渡すオブジェクトには、bar という関数さえありさえすれば良い。

def foo[T](x: T {def bar: Boolean})


呼び出し側では、即席で作ったオブジェクトを渡してみた。

foo(new { def bar = true })

Java と比べると、ものすごくシンプルに記述できる。


javap で foo のメソッドシグネチャを見てみると、その引数は Object なので型チェックはコンパイル時のみ有効なのだと思う。

public final class ducktyping.Sample$ extends java.lang.Object implements scala.ScalaObject{
    public static final ducktyping.Sample$ MODULE$;
    private static java.lang.Class reflClass$Cache1;
    private static java.lang.reflect.Method reflMethod$Cache1;
    public static {};
    public ducktyping.Sample$();
    public void main(java.lang.String[]);
    public boolean foo(java.lang.Object);
    public int $tag()       throws java.rmi.RemoteException;
    public static java.lang.reflect.Method reflMethod$Method1(java.lang.Class);
}

ってことは、おそらく bar メソッドはリフレクションで呼び出しているんだろうと推測。
あまり多用すると遅いかもしれない。