我剛剛讀完the Clojure Polymorphism book,在最後一章討論了這一點。你不妨在那裏看看更多的細節。
它的要點是它們在概念上看起來相同,但它們不是。 他描述了一個語義「gotcha」,因爲Java類也定義了一個名稱空間。例如:
(ns my.ns)
(defprotocol Foo (run [this]))
(ns your.ns)
(defprotocol Foo (run [this]))
(ns user)
(defrecord FooAble [])
(extend-protocol my.ns/Foo
FooAble
(run [this] (println "Foo Me")))
(extend-protocol your.ns/Foo
FooAble
(run [this] (println "Foo You")))
(println 1 (->FooAble))
(def some-foo (->FooAble))
(my.ns/run some-foo) => Foo Me
(your.ns/run some-foo) => Foo You
在Java中,你會試着說
someFoo.run() => Which `run` method...?
所以Clojure中,我可以有一個單一的對象上2種run
方法具有相同的名稱&簽名當且僅當我使用extend-protocol
。如果我嘗試定義聯機崩潰:
(defrecord BeerAble []
my.ns/Beer
(run [this] (println "Beer Me"))
your.ns/Beer
(run [this] (println "Beer You")))
(println 2 (->BeerAble))
(def some-beer (->BeerAble))
(my.ns/run some-beer)
(your.ns/run some-beer)
;=> CompilerException java.lang.ClassFormatError: Duplicate method name&signature in class file user/BeerAble,
所以內聯definnition就像是試圖哈瓦Java接口有兩個void run()
方法。爲了使它工作,你必須將方法名稱改爲myRun
和yourRun
,如果兩個外部庫已經選擇函數名稱run
並且現在發生衝突,那麼這是最好也是不可能的。
具有不讀的書幽靈如果直接回答原來的問題,我不能說,但你不妨實驗一下。除非你有衝突的命名空間/功能問題,否則你應該得到相同的結果。您還可以對您的程序進行配置,以確定其中一個或另一個是否會加速您的程序。
現在仔細看看這段文字,我看不出它應該對他所引用的用例有什麼影響。您可以嘗試驗證答案。
鏈接到電子書不起作用。 –
@AlanThompson謝謝,糾正。 – nha
「原因是特定協議函數的實現相關查找不適用於以這種方式定義的函數。」對我沒有任何意義。他們在實施方式上有所不同,但我不完全清楚正在描述的區別。 –