たぶん、PerlでのDuckTypingはこんなん。
#!/usr/bin/perl package Duck; use strict; use warnings; sub new { my $pkg = shift; bless {@_}, $pkg; } sub quack { 'Gahhh'; } package Swan; sub new { my $pkg = shift; bless {@_}, $pkg; } sub quack { 'Croohhh'; } package main; my $ducks = [ new Duck, new Swan ]; for (@$ducks) { $_->quack; }
で、これと同じことをJavaでやろうとすると、
package sample.ducktype; public interface DuckTypable { Object likeADuck(Object obj); }
package sample.ducktype; import java.util.ArrayList; public class Main { public static void main(String[] args) { ArrayList<DuckTypable> al = new ArrayList<DuckTypable>(); DuckTypable duck = new DuckTypable() { public Object likeADuck(Object obj) { return "I am Duck"; }; }; al.add(duck); DuckTypable swan = new DuckTypable() { public Object likeADuck(Object obj) { return "I am Swan"; }; }; al.add(swan); for (DuckTypable typable : al) { System.out.println(typable.likeADuck(null)); } } }
I am Duck
I am Swan
Reflectionを使わないならこんな感じ。
これだと、DuckTypableインタフェースを実装しないといけないから、DuckTypingとは言えない?
仕様の統一を必要としないことがDuckTypingの肝なんだとしたら、静的言語のJavaではDuck Tyingは絶対に実現できないってことか。
そもそも、現状、大きいシステムを作るのに使われたりする場合のJavaには、DuckTypingは必要ないのか。
コンテキストの短いシステムならこういうのもぜんぜんアリだけど、コンテキストが長いシステムだったら、オブジェクトがとつぜん、アヒルのように振舞ったり白鳥のように振舞ったらビックリしちゃうから、あんまりそぐわないような気がする。
小さいシステムだったら、面倒くさくてJavaは使わないだろうし。