Question

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

Was it helpful?

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.

OTHER TIPS

If you just want to interact with java objects using Clojure and not implement new functionality on them you don't need to worry about protocols. Clojure provides direct access and syntax for java method calls.

For example strings in Clojure are java.lang.String objects:

user=> (type "Really a Java String")
;; java.lang.String

user=> (.toUpperCase "Really a java string")
;;=> "REALLY A JAVA STRING"

Provided your test object class is on the classpath you can create instances like so:

user=> (def a-test-object (mytestpackage/TestObject. "lastName" "firstName" 42))

And call methods like:

user=> (.getAge a-test-object)

See http://clojure.org/java_interop for more info.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top