Search code examples
clojurefunctional-programmingclojurescriptclojure-contrib

Manipulating java objects from clojure


am new at clojure and would like to interact with java objects using clojure. If I have well understood, one can reach this interaction using defprotocol. What I concretely try to do is the following:

1- I have following java class

package mytestspackage;

public class TestObject {

    private String lastName;
    private String firstName;
    private String age;

    public TestObject(String lastName, String firstname, String age) {
        super();
        this.lastName = lastName;
        this.firstName = firstname;
        this.age = age;
    }

    public String getName() {
        return this.lastName;
    }

    public void setName(String name) {
        this.lastName = name;
    }

    public String getFirstname() {
        return this.firstName;
    }

    public void setFirstname(String vorname) {
        this.firstName = vorname;
    }

    public String getAge() {
        return this.age;
    }

    public void setAge(String age) {
        this.age = age;
    }

}

2- I create a clojure protocol that should allow me to access to instances of the above java class TestObject

(ns mytestspackage)
(defprotocol Test
  (first-name [t])
  (last-name [t])
  (age [t]))

Now my question is: where do I concretly implement the methods defined in the protocol and how do I use this implementation to pass TestObject instances to the clojure side and access to values like first name, last name etc...

Any help would be appreciated. Thanks in advance.

Regards, Horace


Solution

  • If I have well understood, one can reach this interaction using defprotocol.

    No, you've got it wrong. Protocols are intended to allow things similar to what interfaces allow in plain java (though more powerful). You can access your Java class without any protocols. Official clojure documentation on this topic: http://clojure.org/java_interop

    Example:

    (ns example
      (:import mytestpackage.TestObject))
    
    ;; This is how we call methods on java objects    
    
    (defn first-name [obj]
      (.getFirstname obj))
    
    (defn last-name [obj]
      (.getName obj))
    
    (defn age [obj]
      (.getAge obj))
    
    (defn set-first-name [obj name]
      (.setFirstname obj name))
    
    (defn set-last-name [obj name]
      (.setName obj name))
    
    (defn set-age [obj age]
      (.setAge obj age))
    
    ;; In REPL
    
    example => (let [x (TestObject. nil nil nil)      ;; This is how we create Java objects
                     x (new TestObject nil nil nil)]  ;; These expressions are equivalent
                  (println (first-name x))
                  (set-first-name x "Name")
                  (println (first-name x))
                  (set-last-name x "Last name")
                  (set-age x "23")
                  (println (last-name x))
                  (println (age x)))
    ;; Outputs
    nil
    Name
    Last name
    23
    

    Please note that this code is nothing more than example intended to introduce java interop. By no means you should write real programs like that, especially if they are mostly in Clojure.