我刚刚读完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
“原因是特定协议函数的实现相关查找不适用于以这种方式定义的函数。”对我没有任何意义。他们在实施方式上有所不同,但我不完全清楚正在描述的区别。 –