clojure';s延伸?真的给我吗?

clojure';s延伸?真的给我吗?,clojure,protocols,Clojure,Protocols,我最近问为什么接口和协议在clojure中不能完全实现: user=> (defprotocol P (foo [self])) P user=> (extend-type Long P) nil user=> (extends? P Long) true user=> (foo 1) IllegalArgumentException No implementation of method: :foo of protocol: #'user/P found for cla

我最近问为什么接口和协议在clojure中不能完全实现:

user=> (defprotocol P (foo [self]))
P
user=> (extend-type Long P)
nil
user=> (extends? P Long)
true
user=> (foo 1)
IllegalArgumentException No implementation of method: :foo of protocol: #'user/P found for class: java.lang.Long  clojure.core/-cache-protocol-fn (core_deftype.clj:527)
并且被告知这是出于互操作的原因,在实践中不会有问题。当然

但是显然,
extends?
并没有告诉我协议和类之间的关系:正如
(extends?pc)
并不意味着我可以在类C的对象上调用
foo
(not(extends?pc))
并不意味着我不能在类C的对象上调用
foo

user=> (defprotocol P (foo [self]))
P
user=> (extend-type Object P (foo [self] 1))
nil
user=> (extends? P Long)
false
user=> (foo 1)
1

现在我很困惑
扩展了哪些信息?
应该提供给我<代码>满足?,另一方面,正确处理第二种情况,但不正确处理第一种情况。

如有疑问,请检查代码:)。
扩展?
的实现如下:

(defn extends? 
  "Returns true if atype extends protocol"
  {:added "1.2"}
  [protocol atype]
  (boolean (or (implements? protocol atype) 
               (get (:impls protocol) atype))))
因此,它只是检查协议是否扩展了
atype
,并不意味着它已经实现了协议的所有方法

:impls
是一个映射,其中键是扩展协议的类型,值是映射,该映射具有该类型协议的方法实现

user=> (defprotocol hello (a [self]))
hello
user=> (:impls hello)
nil
user=> (extend-type String hello)   
nil
user=> (:impls hello)            
{java.lang.String {}}
user=> (extend-type String hello (a [self] 10)) 
nil
user=> (:impls hello)                          
{java.lang.String {:a #<user$eval613$fn__614 user$eval613$fn__614@1d978ea>}}
user=>(defprotocol hello(一个[self]))
你好
user=>(:impls hello)
无
user=>(扩展类型字符串hello)
无
user=>(:impls hello)
{java.lang.String{}
user=>(扩展类型字符串hello(a[self]10))
无
user=>(:impls hello)
{java.lang.String{:a}

另一方面,要使
满足?
您需要传递要检查其协议的对象,而不是
扩展时的类型?
因此,如果查看
满足?
代码,它比
扩展
复杂一些,因为它必须检查要传递的对象的基类是否被扩展根据协议。但是这两个函数只检查类型(或基类型)是否扩展了协议,而不检查您是否实际实现了协议方法。

当然,我去查看了代码,但我真正想要的是更多“当被问到是否扩展了协议时,如果一个类的响应为“是”,我可以期望该类有什么行为?”。您可以期望该类型已经扩展并实现了协议方法(希望遵循良好的编码约定并实现协议的每个方法),因此,如果特定的协议方法是由该类型实现的,那么对该类型的对象调用该协议方法应该有效