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 and 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
by

评论由:sohta发表

这可能超出了这个工单的范围,但协议方法冲突可能导致一些其他类型的错误

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

CompilerException java.lang.VerifyError: (class: user/R1, method: finalize signature: ()Ljava/lang/Object;) Unable to pop operand off an empty stack, compiling: ...
user=> (defprotocol P2 (wait [this]))
P2
user=> (defrecord R2 [] P2 (wait [this]))
user.R2
user=> (def r (->R2))

'user/r

user=> (wait r)
CompilerException java.lang_IllegalArgumentException: No single method: wait of interface: user.P2 found for function: wait of protocol: P2, compiling: ...
user=>
`

在我看来,如果 defprotocol 能够用更详细的信息警告方法冲突会更好。

0
by

评论由: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
by

评论者:bronsa

Ah,当然,谢谢。

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