如何使用与clojure.core函数同名的协议扩展java类?
我试图用以下协议扩展一个简单的java类toxi.color.ColorList:如何使用与clojure.core函数同名的协议扩展java类?,clojure,Clojure,我试图用以下协议扩展一个简单的java类toxi.color.ColorList: (defprotocol countable (count [this])) (extend-protocol countable ColorList (count [this] (.size this))) 当我评估这段代码时,我看到了以下警告 Warning: protocol #'dat00.protocols/countable is overwriting function co
(defprotocol countable
(count [this]))
(extend-protocol countable
ColorList
(count [this]
(.size this)))
当我评估这段代码时,我看到了以下警告
Warning: protocol #'dat00.protocols/countable is overwriting function count
WARNING: count already refers to: #'clojure.core/count in namespace: dat00.protocols, being replaced by: #'dat00.protocols/count
但这很好:
(count (ColorList.))
=> 0
但如果我在同一个文件(或命名空间)中尝试此操作
所以我的问题是:我是否误解了协议的某些细节
谢谢 您遇到了命名空间冲突 定义协议时,您正在当前命名空间中定义分派函数。如果确实要使用“count”,则必须在名称空间声明中排除clojure.core版本
(ns so.protocols
(:refer-clojure :exclude [count]))
现在,在该名称空间中,您可以使用“count”方法定义协议。如果您想在该名称空间中使用count的核心版本,可以在名称空间中为其添加前缀clojure.core/count
然后,协议的用户将希望别名您的命名空间。比如说,
(ns user
(:require [so.protocols :as p]))
因此,
p/count
是您的协议方法,count
是核心。有函数clojure.core/count
和协议中定义的方法count
。正如警告所说:通过创建一个名为count
的方法的接口,您可以将名为count
的别名覆盖到clojure.core/count
(范围5)
返回的LazySeq
对象未实现您的countable
协议。您仍然可以使用(clojure.core/count(range 5))
进行计数
您可能想做的是实现接口而不是自己的接口。多亏了大家 我在这里发布了我为这个案例找到的2个工作解决方案,感谢大家的评论 在所有情况下,我都必须更改函数的名称 似乎多重方法(我还不确定性能后果…)也可以解决这里的表达式问题
(defmulti count type)
(defmethod count toxi.color.ColorList [a]
(.size a))
(defmethod count clojure.lang.LazySeq [a]
(count a))
这对我来说是可行的,尽管我想做的是(在使用ns colission时,我意识到我的概念错误)在同一个ns中使用不同接口的“同名方法”:。。。假设我受到clojure/java interop sintaxis的影响(该参数定义了fn,而不是相反)–协议方法导致在当前名称空间中定义相同名称的函数。当您从某些Clojure代码调用协议方法时,您实际调用的是一个生成的函数,该函数将查找并分派到相应的实现。提前感谢Alex,但是您将如何解决这种情况“当前命名空间冲突”?与任何其他命名空间冲突相同,如下面的答案所述。事实上,它恰好是导致冲突的协议方法并不重要。感谢@Alex,我在下面发布了本案例的两个工作解决方案,使用multimethods和extending protocol,都更改了函数名“您可能想做的是实现clojure.lang.Counted接口,而不是您自己的接口。”-不幸的是,OP希望将协议扩展到现有的Java类-没有迹象表明可以修改该类。然后他应该通过defrecord或使用reify.sorry@lgrapenthin创建Clojure包装。我已取消选中您的解决方案,因为我无法修改Java类,并且,defrecord或reify也不起作用,因为有时我不创建实例:(您有两个选项:1.您创建ToxicLib的全功能Clojure包装器(至少是您直接或间接使用的功能)。这是一个很大的工作,只有在有显著好处的情况下才应该做。2.我的建议是:直接使用Java Interop,这是Clojure中的一个常见习惯用法-
ColorList
甚至不是不变的,所以为什么要使它适合Clojure?只需使用。size
-其他一切都会让代码的读者感到困惑(我认为-这是Clojure coll?)。感谢您解释解决此名称空间重叠的详细信息!但我的问题(没有很好地解释)也与表达式问题有关,然后我想在相同的情况下使用同名方法interfaz。
(defmulti count type)
(defmethod count toxi.color.ColorList [a]
(.size a))
(defmethod count clojure.lang.LazySeq [a]
(count a))
(defprotocol countable
(get-count [this]))
(extend-protocol countable
ColorList
(get-count [this]
(.size this))
clojure.lang.LazySeq
(get-count [this]
(.count this))
)
(get-count (ColorList.)) => 0
(get-count (range 5)) => 5