如何编写一个defprotocol
(和defrecord
来实现它),该方法声明一个与现有函数同名的方法,并动态调度到协议/记录的方法iff我用协议/记录的一个实例调用它,但否则调度到现有的函数?使Clojure的defprotocol在现有功能下可以很好(多态)
例如,我要建立一个支持基本的算术几何助手(只是在这个例子中乘法,以保持它短):
(defprotocol SizeOps
(* [this factor] "Multiply each dimension by factor and return a new Size"))
在这一点上,我已经从得到一些预感推回编译器:
警告:协议# '用户/ SizeOps被重写功能*
警告:*已指:#' clojure.core/*在名称空间:用户,被替换的条件:#'用户/ *
然后执行:
(defrecord Size [width height]
SizeOps
(* [this factor] (Size. (* width factor) (* height factor))))
,编译好了,但是当我尝试使用它,它知道只有*
是一个在我的协议:
(* (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 &答:
- 5438379:
(* "!" 3)
⇒"!!!"
,但掩盖了核心的*
就像在我的例子 - 6492458:不包括像核心功能与
*
操作员工作像Python扩展String
(ns user (:refer-clojure :exclude [*]))
避免了“覆盖”警告,但也避免了该功能:( - 1535235:同样,用手势向使用多方法,但细节
我怀疑正确的解决之道在于像defmulti
和defmethod
或deftype
/derive
下级调度功能的地方,但我不是超级熟悉的细微差别Clojure的runtime polymorphism。而且我要拥有Size
一大堆,Point
,Rectangle
,Circle
等,类型,每个支持+
某个子集,-
,*
,/
操作,所以我很想知道,如果有办法告诉defprotocol
参与/建立任何现有函数的多态性,而不是简单地覆盖它们。