We're updating the issue view to help you get more done. 

Support Abstract Base Classes with Java-only variant of "reify"

Description

Problem:

  • Various Java APIs depend on extension of abstract base classes rather than interfaces

  • "proxy" has limitations (no access to protected fields or super)

  • "proxy" has performance overhead because of an extra layer of functions / parameter boxing etc.

  • "gen-class" is complex and is complected with compilation / bytecode generation

In summary: Clojure does not currently have a good / convenient way to extend a Java abstract base class dynamically.

The proposal is to create a variant of "reify" that allows the extension of a single abstract base class (optionally also with interfaces/protocols). Code generation would occur as if the abstract base class had been directly extended in Java (i.e. with full access to protected members and with fully type-hinted fields).

Since this is a JVM-only construct, it should not affect the portable extension methods in Clojure (deftype etc.). We propose that it is placed in an separate namespace that could become the home for other JVM-specific interop functionality, e.g. "clojure.java.interop"

Proposed solution: The attached patch proposes an implementation for this feature, providing a new `clojure.interop` namespace, containing the `defclass` and `extend-class` macros.

1 2 3 4 5 6 7 8 9 10 11 12 "(defclass name [fields*] options* super-class super-args specs*) Like clojure.core/deftype but can extend a concrete class, override and invoke public and protected methods defined in the super class or one of its base classes and access/set! public and protected fields of those. super-args is a (possibly empty) vector of arguments to the superclass constructor It is possible to invoke a super method while overriding it, by type-hinting the parameter `this` as the super class: (. ^SuperClass this method args*)"
1 2 3 4 5 6 7 8 9 10 11 12 "(extend-class options* super-class super-args specs*) Like clojure.core/reify but can extend a concrete class, override and invoke public and protected methods defined in the super class or one of its base classes and access/set! public and protected fields of those. super-args is a (possibly empty) vector of arguments to the superclass constructor It is possible to invoke a super method while overriding it, by type-hinting the parameter `this` as the super class: (. ^SuperClass this method args*)"

Patch: 0001-CLJ-1225-add-defclass-extend-class-v2.patch

Environment

None

Status

Assignee

Unassigned

Reporter

Mike Anderson

Labels

Approval

Triaged

Patch

None

Affects versions

Release 1.6

Priority

Major