私はちょうど最後の章でこれについて議論するthe Clojure Polymorphism bookを読み終えました。詳細はこちらをご覧ください。
概念の概念は同じであると思われますが、そうではありません。 彼は、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では、あなたは、私がextend-protocol
を使用する場合に限っ
someFoo.run() => Which `run` method...?
だからClojureの中に、私は単一のオブジェクトで同じ名前&シグネチャを持つ2つの
run
メソッドを持つことができると言うしようとするだろう。私はインラインで定義しようとした場合には、クラッシュ:
(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が2つのvoid run()
方法でJavaインタフェースをHAVAしようとしているようなものです。それを動作させるには、メソッド名をmyRun
とyourRun
に変更する必要があります.2つの外部ライブラリがすでに関数名run
を選択していて、今クラッシュしている場合は不可能です。
Specterの本を読んでいないと、これは元の質問に直接答えることはできませんが、ちょっと試してみることもできます。クラッシュする名前空間/関数の問題がない限り、どちらの場合でも同じ結果が得られるはずです。また、あなたのプログラムをプロファイリングして、あなたのプログラムのスピードアップを判断することもできます。
より詳しくは、彼が引用したユースケースには違いがあるはずがありません。あなたは答えを検証するために実験をすることができます。
電子ブックへのリンクが機能しません。 –
@AlanThompsonありがとう、訂正しました。 – nha
"その理由は、特定のプロトコル関数の実装依存のルックアップは、そのように定義された関数では機能しないからです。私には意味がありません。彼らは実装方法が異なりますが、どのような違いが記述されているのかはまったくわかりません。 –