2024 Clojure 状况调查! 中分享您的想法。

欢迎!请参阅 关于 页面以了解更多关于其运作方式的信息。

0
Clojure

在尝试定义包含 "clear" 方法名的协议时似乎存在问题。

(defprotocol PClear

 (clear (link: o)))

=> PClear

(defrecord Foo (link: )

 PClear 
   (clear (link: o) o))

=> CompilerException java.lang.ClassFormatError: Duplicate method name&signature in class file xxxx/Foo, compiling:(NO_SOURCE_PATH:1:1)

我猜测这是由于与底层实现中 Java 方法 Collection.clear() 的名称冲突。然而,错误信息非常不明确,而且在我看来,潜在的冲突似乎没有文档记录。

似乎有两种方法可以解决这个问题:
a) 禁止使用 "clear" 作为协议方法名(在这种情况下,错误应该更具体,规则也应该有记录)
b) 在类文件格式中找到支持它的方式(可能通过使用 JVM 返回类型进行超载,因为 Collection.clear() 返回 void??)

6 答案

0

评论者:bronsa

Mike,JVM 不支持返回类型过载,因此您的第二个建议在技术上是不可能的。

阅读 defrecord 的文档{quote}该类将自动生成几个 (clojure.lang) 接口的实现:IObj(元数据支持)和
IPersistentMap,以及它们的所有超接口。
{quote}
{quote}

也许应该在这里提到 java.util.Collection(或者更好,java.util.Map)。

0

评论者:alexmiller

我认为这是一个文档增强请求。

0

评论者:sohta

这可能与本次工单的范围无关,但协议方法冲突可能会引起其他类型的错误

`
user=> (defprotocol P1 (finalize [this]))
P1
user=> (defrecord R1 [] P1 (finalize [this]))

编译器异常 java.lang.VerifyError: (类:user/R1,方法:finalize 签名:()Ljava/lang/Object;) 无法从空栈中弹出操作数,编译过程中:...
user=> (defprotocol P2 (wait [this]))
P2
user=> (defrecord R2 [] P2 (wait [this]))
user.R2
user=> (def r (<-R2))

'user/r

user=> (wait r)
编译器异常 java.lang.IllegalArgumentException: 在协议 P2 中找不到唯一的方法:wait,为其提供的函数:wait 编译过程中:...
user=>
`

在我看来,如果 defprotocol 能够用一个更具信息量的消息来警告方法冲突,那会更好。

0

评论者:mikera

@Nicola Mometto:我认为 JVM 确实支持泛型返回类型

"请注意,在类中可能有多个匹配的方法,因为尽管 Java 语言禁止声明签名相同但返回类型不同的多个方法,但 Java 虚拟机并未这样做。这种虚拟机的更大灵活性可以用于实现各种语言特性。例如,协变返回可以通过桥梁方法实现;桥梁方法和被重写的方法将具有相同的签名但不同的返回类型。"

参见:http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getMethod-java.lang.String-java.lang.Class...-

0

评论者:bronsa

Ah,当然,谢谢。

0
参考:https://clojure.atlassian.net/browse/CLJ-1791(由 mikera 报告)
...