我试图用这个协议扩展一个简单的java类toxi.color.ColorList
:
(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 (range 5))
=> IllegalArgumentException No implementation of method: :count of protocol: #'dat00.protocols/countable found for class: clojure.lang.LazySeq clojure.core/-cache-protocol-fn (core_deftype.clj:541)
所以我的问题是:
我是否误解了有关协议的一些细节?
谢谢!
答案 0 :(得分:4)
您有命名空间冲突。
定义协议时,您将在当前命名空间中定义调度函数。如果确实想要使用“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
是核心。
答案 1 :(得分:4)
您的协议clojure.core/count
中定义了函数count
和方法countable
。如警告所示:通过创建具有名为count
的方法的接口,将名为clojure.core/count
的别名覆盖为count
。
LazySeq
返回的(range 5)
对象未实现您的countable
协议。你仍然可以用(clojure.core/count (range 5))
计算它。
您可能要做的是实现clojure.lang.Counted
界面而不是您自己的界面。
答案 2 :(得分:0)
感谢所有人,
我在这里发布了2个工作解决方案我已经达成了这个案例,感谢所有的评论
在所有情况下,我都必须更改功能的名称
似乎多方法(我还不确定性能后果......)可以解决这里的表达问题
(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
对我来说很有用,虽然我想做的事情(以及我意识到我的概念错误的ns colission)是在同一个ns中使用不同接口的“同名方法”:) ...假设我受到clojure / java interop sintaxis的影响(参数定义了fn而不是相反) -