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} 该类将自动生成实现多个接口的代码: IObj (metadata 支持) 和
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: No single method: wait of interface: user.P2 found for function: wait of protocol: P2, compiling: ...
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

啊,是的,当然,谢谢。

0
...