Search code examples
clojureclojure-java-interop

Extend java class in clojure: how to override only one of two similar methods?


I have the following java class.

public class Toto {
    public void aMethod(A a) {
        System.out.println("A " + a);   
    }

    public void aMethod(B b) {
        System.out.println("B " + b);
    }
}

I want to override aMethod(A a) but not aMethod(B b). The only way I could do that was:

(ns titi
    (:gen-class :extends Toto
     :exposes-method {aMethod parentMethod}))

(defn- -aMethod [this x]
    (if (= (type x) A)
        (println "ok do something here")
        (.parentMethod this x)))

Is there a better way to do this? (I mean without checking type of x myself).


Solution

  • According to http://dishevelled.net/Tricky-uses-of-Clojure-gen-class-and-AOT-compilation.html, with :gen-class it is possible to override by signature but I couldn't find documentation on that, so I guess it can be considered "internals" and it may break in the future.

    Anyway, supposing you have your Toto class in package jpkg together with two empty classes A and B, this works for me:

    (ns Titi
    (:import [jpkg A])
        (:gen-class :extends jpkg.Toto
                    :exposes-method [aMethod]))
    
    (defn- -aMethod-A [this x]
        (println "clj a"))
    

    As the following main namespace:

    (ns main
        (:import [jpkg A B]))
    
    (set! *warn-on-reflection* true)
    
    (defn -main []
        (. (new Titi) aMethod (new A))
        (. (new Titi) aMethod (new B)))
    

    prints:

    clj a
    B jpkg.B@6631f5ca
    

    instead of:

    clj a
    clj a
    

    Type hints instead seem not to help here.