Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding multi-arity methods in proxy in clojure

I have a java class that has 2 methods with same but different arities (one take no arguments, other takes 1 argument). I create a proxy that overrides both this methods. The problem is that if no-arg method is called from this java class - base implementation is called instead of proxie's. But if I call no-arg method directly on obj - correct proxy method is invoked. Can someone explain this behavior?

Test.java:

package example;

public abstract class Test {

    public void callMethods(Object obj){
        callMethods();
        callMethods2();
    }

    public void callMethods() {
        System.out.println("Default callMethods");
    }

    public void callMethods2() {
        System.out.println("Default callMethods2");
    }

}

run.clj:

(let [obj (proxy [example.Test] []
            (callMethods
              ([] (println "Overridden callMethods"))
              ([obj] (proxy-super callMethods obj)))
            (callMethods2
              ([] (println "Overridden callMethods2"))))]
  (.callMethods obj)
  (.callMethods obj :test))

Output:

Overridden callMethods
Default callMethods
Overridden callMethods2

Expected output:

Overridden callMethods
Overridden callMethods
Overridden callMethods2
like image 229
Mikita Belahlazau Avatar asked Oct 30 '12 07:10

Mikita Belahlazau


1 Answers

Proxy maintains a map of the methods it is proxying for this object. Any call in this map it handles with it's method, the others call to the object. proxy-super does it's magic by removing itself form the functions method map, calling itself and putting itself back afterwords. Durring the call any calls to that method of the proxy object will fall through to the proxied object.

  • The first line of output comes from the proxied call and you see the overridden output
  • The second line comes from the super's method with zero arguments because when that call happens the overriding method is not in the objects proxied methods map.
  • The third line gets proxied because that method is in the objects proxied methods map.

A very similar scenario is described at the end of this post by Meikel Brandmeyer. I suspect the answer is to use gen-class instead of proxy

like image 58
Arthur Ulfeldt Avatar answered Nov 01 '22 17:11

Arthur Ulfeldt