Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clojure: Can't access non-public fields in the same package

Tags:

clojure

In my clojure program I cannot access package scoped fields of the java class com.foo.Foo although I am in the namespace "com.foo" (via "(ns com.foo)" at the top of my clojure program). However, public fields in com.foo.Foo are accessible.

Why?

like image 593
frank Avatar asked Nov 14 '22 01:11

frank


1 Answers

Two problems here:

First, the namespace com.foo is compiled to a class foo_whatever in package com; it's not compiled to a class in package com.foo.

See:

user> (ns com.foo)
nil
com.foo> 
nil
com.foo> (defn hello[] "hello !")
#'com.foo/hello
com.foo> (class hello)
com.foo$hello
com.foo> (ns com.foo.hello)
nil
com.foo.hello> (defn hi[] "hi !")
#'com.foo.hello/hi
com.foo.hello> (class hi)
com.foo.hello$hi

Second, when looking for constructors or fields, the Clojure compiler uses methods getConstructor and getFields from java.lang.Class, which, by spec, only return the public constructors and public fields.

So, bad luck here. It seems you won't be able to access package-protected fields.

Edit, answering comments. The best approach for accessing package-level fields in legacy Java code would be to write a class in Java that wraps the existing class and which exposes the package protected methods and fields from that class with public methods. This way, you have more control over the name and package of the generated class.

This wrapper is a small amount of Java code, and from there you can access the fields from Clojure code.

like image 129
Leonel Avatar answered Jun 13 '23 18:06

Leonel