Options for creating Java classes in Clojure
There are a few different ways to create Java classes in Clojure, so what are the tradeoffs when picking between gen-class
, proxy
, and reify
in Clojure? (are there other ways to create Java classes that I haven't listed?)
My basic understanding is that I hav开发者_JAVA百科e listed these constructs in decreasing order of power.
Use gen-class
when you want a named class or you want to add new methods to objects you create. gen-class
relies on AOT compilation.
When you want an anonymous, one-off implementation of a type you use reify
or proxy
. They do not rely on AOT compilation. Here are their differences:
reify
only supports protocols or interfaces,proxy
also supports concrete superclasses.reify
uses true class methods,proxy
uses external functions.- Because of #2,
reify
uses direct method lookup, whileproxy
uses a map for method lookup. - Because of #3,
reify
does not support dynamic swapping of methods, butproxy
does.
reify
will perform better than proxy
, so you should always use reify
when possible. Only use proxy
when reify
's constraints are too prohibitive.
In addition to gen-class, proxy and reify, we have defrecord and deftype. These latter two options should be your first choices for the creation of named java classes (and in the case of defrecord, your first choice for any kind of struct with named components.)
The datatypes page on clojure.org is a good reference on this topic. Defrecord, deftype and reify are newer than gen-class and proxy, having been introduced in version 1.2 (I think -- possibly 1.1). Defrecord and deftype both create classes that conform to interfaces, but do not allow for inheritance. If you need inheritance, gen-class (and proxy for anonymous classes) is still your only option.
Defrecord and deftype differ in what you are given for free. Defrecord automatically creates a class which conforms to IPersistentMap and ISeq. Deftype, on the other hand, gives you more control over your class, even allowing for mutable fields (not allowed in defrecord). In general, deftype is intended for low-level implementation of data structures, whereas defrecord is intended for most day-to-day use.
精彩评论