Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Compiler by
edited by

How to create a Java class with a private final field in Clojure?

ClojureDocs for gen-class says that state field will be public

:state name - if supplied, a public final instance field with the given name will be

So, in other words, do we have a way to create a class and instantiate a java object with the encapsulated state?

2 Answers

+4 votes
selected by
Best answer

In short, no. As you mention in the docs, gen-class state fields will be public final fields. However, that field can be (for example), an atom that is statefully modified by the implementation methods. In general, we do not give much weight to encapsulation in Clojure - instead preferring to make things visible, but "safe" (via immutability). To quote Rich from https://clojure.org/reference/datatypes, "encapsulation is folly".

gen-class is not a general purpose DSL for generating all possible Java classes. It is a tool to generate classes in a certain style in line with Clojure's aesthetics.

Another path however to something along these lines is to use a deftype, which can have private mutable fields, exposed by implementing interfaces or protocols inline. The deftype fields can have meta of either ^:volatile-mutable or ^:unsynchronized-mutable, both of which will become private fields.

+1 vote

Aside from deftype with mutable fields, you can resort to libraries like JiSE to get more control over defining classes. This is not common, but perhaps useful in some cases.