ProxyでMixin的な処理
が出来るんじゃないかと思ったけど、これは流石にかなり昔にやられてた。
ProxyでMixin - lambda {|diary| lambda { diary.succ! } }.call(hatena)
呼び出されたメソッドがどのクラス/インタフェースに載ってるのかをMethodのgetDeclaringClass()で取得出来るようなので、MixinInvocationHandlerの実装をメソッド名ベースでなくインタフェースベースに変えればオーバーロードでも平気になる。
class MixinInvocationHandler implements InvocationHandler { private Map objectMap = new HashMap(); public MixinInvocationHandler(Object[] objects) { for (int i = 0; i < objects.length; i++) { Class[] interfaces = objects[i].getClass().getInterfaces(); for (int j = 0; j < interfaces.length; j++) { objectMap.put(interfaces[j], objects[i]); } } } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object object = objectMap.get(method.getDeclaringClass()); if (object == null) return null; return method.invoke(object, args); } }
cat.run()はCatのrun()が呼ばれても良さそうなのに、getDeclaringClass()を取ると実際はCarの方のrun()が呼ばれている(Proxyを作る時に指定するインタフェースの順序に依存する。) invokeinterfaceのメソッド決定方法のせいかも。