请在2024 Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面以了解更多有关该功能的信息。

+3
Java互操作

问题
- 不同的Java API 依赖于扩展抽象基类,而不是接口
- "proxy" 有局限性(不能访问受保护的字段或超类)
- "proxy" 由于额外一层函数/参数装箱等,性能开销较大
- "gen-class" 复杂且与编译/字节码生成相关联

总结:Clojure 目前没有一个好/方便的方法来动态扩展 Java 抽象基类。

提议创建 "reify" 的一个变体,允许扩展单个抽象基类(可选地也可以是接口/协议)。代码生成将像在 Java 中直接扩展抽象基类一样执行(即,具有完全访问受保护的成员,并且具有完全类型提示的字段)。

因为这是一个 JVM 仅有的结构,它不应该影响 Clojure 的可移植扩展方法(如 deftype 等)。我们提议将其放置在一个单独的命名空间中,这个命名空间可以成为其他 JVM 特定互操作功能(例如,"clojure.java.interop")的家园。

建议的解决方案: 附加的补丁提议了此功能的实现,提供一个新的 clojure.interop 命名空间,包含 defclassextend-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

5 答案

+1

评论由:bronsa发表

附上本功能的建议实现版本

+1

评论由:bronsa发表

更新的补丁与v1相同,但在master基础上刷新

+1
参考: https://clojure.atlassian.net/browse/CLJ-1255 (由mikera报告)
我正在开发的代码也能从中受益
class="qa-avatar-link">
我们对这个想法很感兴趣,并且已经多次浏览了这个工单,但这里的补丁中修改编译器的方法比我们希望的更具侵略性。自从我们上次讨论这个问题以来已经有一段时间了,所以我记不起细节
0

评论由:alexmiller发表

Rich说:我们不希望在可移植的结构(reify,deftype)中支持抽象类。然而,这将被视为一个新的仅限Java的结构(extend-class 或 reify-class)。如果你能适当修改工单,我们将将其移回分类状态。

0

评论由:bronsa发表

有关所提议实现的更多文档可在此找到:https://docs.google.com/document/d/1OcewjSpxmeFRQ3TizcaRRwlV34T8wl4wVED138FHFFE,未压缩的提交可在https://github.com/clojure/clojure/compare/master...Bronsa:defclass找到

...