2012-05-30 64 views
1

最近,我問爲什麼的接口和協議可以用Clojure來實現不完全: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? P C)並不意味着我可以在C類的對象調用foo(not (extends? P C))並不意味着我不能對對象調用foo C類:

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

現在我感到應該什麼樣的信息extends?給我... satisfies?,另一方面很困惑,正確處理第二種情況,但不是第一個。

回答

3

當有疑問檢查代碼:)。的extends?實現是這樣的:

(defn extends? 
    "Returns true if atype extends protocol" 
    {:added "1.2"} 
    [protocol atype] 
    (boolean (or (implements? protocol atype) 
       (get (:impls protocol) atype)))) 

所以它只是檢查是否atype已通過協議延長,但這並不意味着它已經實現了協議中的所有方法。

:impls是一個映射,其中key是擴展協議的類型,值是map,該映射具有該類型協議的實現方法。

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 [email protected]>}} 

在另一方面,以satisfies?需要傳遞和要檢查協議的對象不是那種如在extends?情況下,所以,如果你看一下satisfies?代碼更復雜一點,然後extends,因爲它必須檢查被協議擴展傳遞的對象的基類。但是這兩個函數只是檢查類型(或基類型)是否擴展了協議,並且它們不檢查是否實際實現了協議方法。

+0

當然,我去看了一下代碼,但是我真正在尋找的是更多的「我可以期望什麼樣的行爲,當被問及是否擴展協議時,回答yes」。 – antony

+0

您可以預期該類型已經擴展並實現了協議方法(希望遵循良好的編碼規範和實現協議的每種方法),因此在實現特定協議方法的情況下調用該類型的對象上的協議方法應該可以工作按類型 – Ankur