问题
- 不同的Java API 依赖于扩展抽象基类,而不是接口
- "proxy" 有局限性(不能访问受保护的字段或超类)
- "proxy" 由于额外一层函数/参数装箱等,性能开销较大
- "gen-class" 复杂且与编译/字节码生成相关联
总结:Clojure 目前没有一个好/方便的方法来动态扩展 Java 抽象基类。
提议创建 "reify" 的一个变体,允许扩展单个抽象基类(可选地也可以是接口/协议)。代码生成将像在 Java 中直接扩展抽象基类一样执行(即,具有完全访问受保护的成员,并且具有完全类型提示的字段)。
因为这是一个 JVM 仅有的结构,它不应该影响 Clojure 的可移植扩展方法(如 deftype 等)。我们提议将其放置在一个单独的命名空间中,这个命名空间可以成为其他 JVM 特定互操作功能(例如,"clojure.java.interop")的家园。
建议的解决方案: 附加的补丁提议了此功能的实现,提供一个新的 clojure.interop
命名空间,包含 defclass
和 extend-class
宏。
`
``(defclass name [fields*] options super-class super-args specs)``
类似于 clojure.core/deftype,但可以扩展一个具体的类,重载
并调用在超类或
其基类中定义的公共和受保护的公共方法,并访问/设置那些的公共和受保护的字段。
super-args 是传递给超类构造函数的(可能为空)向量参数
构造函数
通过将参数 this
类型提示为超类:(. ^SuperClass this method args*),可以调用重写的方法
参数
``(extend-class options super-class super-args specs)``
`
类似于 clojure.core/reify,但可以扩展一个具体的类,重载
参数 this
,将其类型提示为超类:(. ^SuperClass this method args*)
并调用在超类或
其基类中定义的公共和受保护的公共方法,并访问/设置那些的公共和受保护的字段。
super-args 是传递给超类构造函数的(可能为空)向量参数
构造函数
通过将参数 this
类型提示为超类:(. ^SuperClass this method args*),可以调用重写的方法
参数
``
补丁: 0001-CLJ-1225-add-defclass-extend-class-v2.patch