既存の関数と同じ名前のメソッドを宣言し、プロトコル/レコードのメソッドに動的にディスパッチするdefprotocol
(およびそれを実装するにはdefrecord
)を書くにはどうすればよいですか? iff私はそれをプロトコル/レコードのインスタンスで呼びますが、それ以外の場合は既存の関数にディスパッチしますか?既存の関数でClojureのdefprotocolをうまく動かす(多態的に)
例えば、私は基本的な算術演算をサポートしているジオメトリヘルパー(わずかにそれを維持するために、この例では乗算)作成したい:私はすでに、一部の予感プッシュバックを取得しています。この時点で
(defprotocol SizeOps
(* [this factor] "Multiply each dimension by factor and return a new Size"))
をコンパイラ:
警告:プロトコル# 'ユーザー/ SizeOpsが上書きされる機能*
大丈夫コンパイル
WARNING:*すでに言及へ:#' clojure.core/*名前空間に:ユーザー、交換されることによって:# 'ユーザー/ *(defrecord Size [width height] SizeOps (* [this factor] (Size. (* width factor) (* height factor))))
が、私はそれを使用しようとすると、それは知っているだけ
*
は私のプロトコルの1です:その後
実装
(* (Size. 1 2) 10)
IllegalArgumentExceptionがメソッドの実装はありません::*プロトコルの: '' user/SizeOpsはクラスのjava.lang.Longに見つかりました
私は完全に私の実装ではコア*
機能を指定することでこの問題を回避ハックすることができます
(defrecord Size [width height]
SizeOps
(* [this factor] (Size. (clojure.core/* width factor) (clojure.core/* height factor))))
(* (Size. 1 2) 10)
#のuser.Size {:幅10、:高さ20}
しかし、私は取得後で(* 3 4)
に電話をかけようとすると、同じIllegalArgumentException
となります。私はdefrecord
の実装でclojure.core/*
という名前のスペースを使用して胃を胃にすることができますが、私はSize
のレコードとLong
、Double
のようにいつものように*
と呼ぶことができます。
同様のQ & A:
- 5438379:ちょうど
- 6492458私の例のようにコアの
*
を(* "!" 3)
⇒"!!!"
が、不明瞭::などのコア機能を除くPythonのように動作します*
オペレータとString
を拡張(ns user (:refer-clojure :exclude [*]))
は、 "上書き"警告を回避しますが、その機能を回避します。( - 1535235:同じ、multimethodを使用に向けたジェスチャーが、詳細なしで
私は適切なソリューションをdefmulti
とdefmethod
またはdeftype
/derive
のような低レベルのディスパッチ機能のどこかにある疑いがあるが、私はのニュアンスを持つスーパー慣れていませんよClojureのruntime polymorphism。そして、私はつもりだ、それぞれが+
、-
、*
、/
操作のいくつかのサブセットをサポートするタイプをなどSize
、Point
、Rectangle
、Circle
、全体のホストを持っているので、私は伝える方法がありますかどうかを知るのが大好きですdefprotocol
既存の関数のポリモーフィズムに参加する/構築することは、既存の関数を単純に上書きするのではなく、