ダックタイピングとは。

ダック・タイピング(duck typing)とは、Smalltalk、Python、Rubyなどのいくつかの動的型付けオブジェクト指向プログラミング言語に特徴的な型付けの作法のことである。それらの言語ではオブジェクト(変数の値)に何ができるかはオブジェクトそのものが決定する。つまり、オブジェクトがあるインタフェースのすべてのメソッドを持っているならば、たとえそのクラスがそのインタフェースを宣言的に実装していなくとも、オブジェクトはそのインタフェースを実行時に実装しているとみなせる、ということである。それはまた、同じインタフェースを実装するオブジェクト同士が、それぞれがどのような継承階層を持っているのかということと無関係に、相互に交換可能であるという意味でもある。

ダック・タイピング - Wikipedia

Ruby で書くとこんな感じ。メソッドが同じ名前であれば、継承階層なんて関係なしに呼び出せる。これがダックタイピング。アヒル(Duck)とミミック(Mimic)のクラスには継承関係は無い。


class Quacker
  def doQuack(duck, n)
    duck.quack(n)
  end
end
 
class Duck
  def quack(n)
    puts 'quack!' * n
  end
end
 
class Mimic
  def quack(n)
    puts 'quack!!' * n
  end
end
 
Quacker.new.doQuack(Duck.new, 2)
Quacker.new.doQuack(Mimic.new, 3)

実行結果:


quack!quack!
quack!!quack!!quack!!

Java ではダックタイピングは言語仕様的に無理(;´∀`) ジェネリクスでなんとかならないかなと思ったけどダメだった。もうリフレクション使うぐらいしか。

アヒル(Duck)とミミック(Mimic)のクラスに継承関係が無いように Java のコードを書いてみる。


import java.lang.reflect.Method;
 
public class DuckTyping {
 
  public static void main(String[] args) {
    new Quacker().doQuack(new Duck(), 2);
    new Quacker().doQuack(new Mimic(), 3);
  }
 
  public static class Quacker {
    public void doQuack(Object duck, int n) {
      try {
        Class cls = duck.getClass();
        Method method = cls.getMethod("quack", new Class[] { int.class });
        method.invoke(duck, n);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
 
  public static class Duck {
    public void quack(int n) {
      for (int i = 0; i < n; i++) {
        System.out.print("quack!");
      }
      System.out.println();
    }
  }
 
  public static class Mimic {
    public void quack(int n) {
      for (int i = 0; i < n; i++) {
        System.out.print("quack!!");
      }
      System.out.println();
    }
  }
}

実行結果:


quack!quack!
quack!!quack!!quack!!

結局リフレクションを使うしかなかった。。。

他に Java でダックタイピングを試した人がいるはず、と思って探してみたら、

呼び出したいメソッドと同じインターフェースを持つメソッドを Interface で宣言しておいて、それをリフレクションでオブジェクトに追加する、という手法を試している人がいた。これはすごい。
100%ピュアJavaでダックタイピングを実現してみたら、違う何かになっていた・・・ - 豆無日記

tags: Java ruby

Posted by NI-Lab. (@nilab)