protocols and interfaces

61 views
Skip to first unread message

drewn

unread,
Feb 10, 2012, 3:13:24 AM2/10/12
to Clojure
I've just started learning protocols, deftype, etc. The first thing I
did was try to extend a Clojure type (maps) to operate as a
specialized Java Swing interface (AttributeSet), forgetting that
interfaces are not protocols; i.e.

(extend-type clojure.lang.PersistentArrayMap
javax.swing.text.AttributeSet
(getAttribute [this k]
(get this k)))

Is there any way of doing what is intended here: get Clojure maps to
implement Java's AttributeSet? I've seen Chas Emerick's flowchart,
but I'm still trying to wrap my head around all the choices.

Thanks, Andrew

Stuart Sierra

unread,
Feb 10, 2012, 9:24:42 AM2/10/12
to clo...@googlegroups.com
Nope, can't be done. Java interfaces can't do this.

Java 8 may have "Interface Injection" which will make this possible.
-S

drewn

unread,
Feb 10, 2012, 12:51:39 PM2/10/12
to Clojure
> Nope, can't be done. Java interfaces can't do this.

I'm glad I asked the question. Given that it can't be done, any
suggestions for the best way of handling this interop scenario?

Aaron Cohen

unread,
Feb 10, 2012, 1:07:37 PM2/10/12
to clo...@googlegroups.com
On Fri, Feb 10, 2012 at 3:13 AM, drewn <nayl...@gmail.com> wrote:
> I've just started learning protocols, deftype, etc.  The first thing I
> did was try to extend a Clojure type (maps) to operate as a
> specialized Java Swing interface (AttributeSet), forgetting that
> interfaces are not protocols; i.e.
>
> (extend-type clojure.lang.PersistentArrayMap
>  javax.swing.text.AttributeSet
>  (getAttribute [this k]
>                (get this k)))

I think in this case you should be able to use proxy, maybe.

user=> (defn attribute-list [map] (proxy [javax.swing.text.AttributeSet] []
(getAttribute [k] (get map k))))

user=> (.getAttribute (attribute-list {:a 1 :b 2}) :a)
1

Cedric Greevey

unread,
Feb 10, 2012, 1:32:09 PM2/10/12
to clo...@googlegroups.com

There's also defrecord:

(defrecord foo [my basis keys]
the.JavaInterface
(javaIfaceMethod [this foo] ...))

which will work in the specific case that you want "a Clojure map that
implements a particular Java interface". Records behave partially as
Clojure maps. For more general mixins, proxy, reify, and deftype are
your friends, and even gen-class may be needed in some instances.

drewn

unread,
Feb 10, 2012, 3:36:05 PM2/10/12
to Clojure
> There's also defrecord

I considered using that, but I need to do something more with the
constructor (e.g. convert the map into a Java array for internal
use). Also, defrecords only takes positional arguments, which will be
hard to use with tens of arguments. (An alternative is just to pass
in one argument as a map itself, but that seems to defeat the
purpose.)

On Feb 10, 10:32 am, Cedric Greevey <cgree...@gmail.com> wrote:
> On Fri, Feb 10, 2012 at 1:07 PM, Aaron Cohen <aa...@assonance.org> wrote:
Reply all
Reply to author
Forward
0 new messages