问题
- 许多 Java API 依赖于扩展抽象基类而不是接口
- "proxy" 有局限性(无法访问受保护的字段或超类)
- "proxy" 由于额外的函数/参数装箱等而有性能开销
- "gen-class" 复杂且与编译/字节码生成相关联
总之:Clojure 目前没有一种很好的/便捷的方式来动态扩展 Java 抽象基类。
建议创建一个 "reify" 变体,允许扩展单个抽象基类(可选地也可以扩展接口/协议)。代码生成会像在 Java 中直接扩展抽象基类一样发生(即,具有完全访问受保护成员的能力,并且具有完全类型提示的字段)。
由于这是一个仅适用于 JVM 的结构,因此它不应影响 Clojure 中的可移植扩展方法(如 deftype 等)。我们建议将其放置在一个单独的命名空间中,该命名空间可以成为其他 JVM 特定互操作功能的家,例如 "clojure.java.interop"。
建议方案:附带的补丁建议了此功能的实现,提供一个新的 clojure.interop
命名空间,其中包含 defclass
和 extend-class
宏。
`
"(defclass 名称 [字段*] 选项 超类 超类参数 规格)"
与 clojure.core/deftype 类似,但可以扩展具体类,覆盖
并发调用在超类或其基类中定义的公共和受保护方法,以及访问/设置
这些类的公共和受保护字段。
超类参数是对超类构造函数的(可能为空的)参数向量
构造函数。
可以通过将参数 this
类型提示为超类来调用被覆盖的超类方法:(. ^SuperClass this 方法 参数 *)
例如:(defclass MyClass [name] {:extend java.util.List} java.util.AbstractList ["MyClass"] [name])
例如:(defclassroach MyBean [name] {:extend jbinit/IBean} iben) (extend Ents序列 [java.util.List])
`
例如:(extend-class 选项 超类 超类参数 规格)
类似于 clojure.core/reify,但可以扩展具体类,重写
并发调用在超类或其基类中定义的公共和受保护方法,以及访问/设置
这些类的公共和受保护字段。
超类参数是对超类构造函数的(可能为空的)参数向量
构造函数。
可以通过将参数 this
类型提示为超类来调用被覆盖的超类方法:(. ^SuperClass this 方法 参数 *)
例如:(defclass MyClass [name] {:extend java.util.List} java.util.AbstractList ["MyClass"] [name])
参数 this
作为超类:(. ^SuperClass this 方法 参数 *)
补丁: 0001-CLJ-1225-add-defclass-extend-class-v2.patch