0

根据我的研究,扩展 Java 类的方法基本上是使用命名空间中的 gen-class 或使用代理。但是查看Clojure 类型选择流程图,似乎建议我可以使用记录来扩展 Java 类:

  1. 该类型是否需要扩展 Java 类或实现任何接口?是的
  2. 你需要一个命名类型还是只需要一个匿名类型的实例?命名类型
  3. 您是否需要能够从 Java 中静态引用该类?不
  4. 您的班级是否对领域价值进行建模 - 从而受益于类似 hasmap 的功能和语义?是的

使用定义记录

所以问题是......如何?

例如(来自这个):

public final class Second extends Struct {
    public final Signed32 a_number = new Signed32();
    public Second(final Runtime runtime) {
        super(runtime);
    }
}

public final class Top extends Struct {              
    public final Second second = inner(new Second(getRuntime()));  
    public final Second[] seconds = array(new Second[5]);
    public final Signed32 another_number = new Signed32();
    public final Signed32[] more_numbers = array(new Signed32[5]);
    public Top(final Runtime runtime) {
        super(runtime);
    }
}

难道我...

(defrecord Second)
(extend jnr.ffi.Struct
        Second)

?

4

2 回答 2

0

为什么需要命名类型?如果,如您所说,您不需要从 Java 中静态引用它,那么我看不出有什么特别的理由来命名该类型。如果你正确回答了这个问题,它会引导你proxy。您的问题是您选择了不一致的答案:您说您需要一个命名类,但对您可能需要一个命名的任何原因都没有回答是。流程图考虑的原因是 Java 代码可能希望通过名称来引用您的代码,在这种情况下gen-class. 但是,一方面说您必须扩展 Java 类,另一方面说您的新类型将是一个简单的数据载体,对域值进行建模,这毫无意义。Clojure 记录在这方面做得很好,但是拥有来自 Java 的令人讨厌的可变基类并不能成为一个好的域对象。

也就是说,如果您对“为域类型建模”回答“否”,它会引导您进入deftype,它也不能扩展类。如果你想扩展一个类,我认为它允许你逃离“互操作区”是一个错误:最好将接口和子类分开,但流程图只能这么大。

FWIW对原始流程图帖子的评论包括您的问题,作者的回答,回应了我的使用建议proxy以及流程图已经足够大的问题:

第一个决定并不完全表明您需要扩展一个类——它包括实现接口。所以,那里有一点模棱两可。当然,你在 gen-class-land 那里,但我认为,为了消除歧义,更多地分解事物会使流程图变得更大一些。

FWIW,我会亲自将命名类型要求放在那里,使用代理,然后只定义 (class (create-proxy-instance ...)) 的结果?检查等(假设这就是您需要命名类型的原因)。

于 2020-09-02T05:34:49.493 回答
0

我认为流程图是错误的。检查Clojure - 数据类型:deftype、defrecord 和 reify文档,我们可以看到:

  • deftype/defrecord 可以实现一个或多个协议和/或接口

没有提到扩展现有类。确实,查看文档defrecord本身并没有提到扩展现有类,除非Object是特殊情况。

抱歉,它看起来要么是您的唯一选择,proxy要么gen-class是您唯一的选择。

于 2020-09-02T05:02:28.430 回答