目前,虽然可以将协议扩展到多个接口,但没有像多方法中的 prefer-method 一样的机制来选择一个实现而不是另一个,因此,如果多个接口匹配,则随机选择一个。
这是一个问题的特例,尝试处理通用的记录和映射(这在 tools.analyzer 中出现):当扩展协议到 IRecord 和 IPersistentMap 时,无法使 IRecord 实现被选择而不是 IPersistentMap 实现因此无法使用协议。
附带的补丁添加了一个类似于 prefer-method 但用于协议的 prefer-proto 函数。
如果没有使用 prefer-proto,则不会造成性能损失,如果使用,则在第一次协议方法分发时搜索优先级表会有性能损失,但对于后续调用,协议方法缓存将消除这种损失。
示例
user=> (defprotocol p (f [_])) p user=> (extend-protocol p clojure.lang.Counted (f [_] 1) clojure.lang.IObj (f [_] 2)) nil user=> (f [1]) 2 user=> (prefer-proto p clojure.lang.Counted clojure.lang.IObj) nil user=> (f [1]) 1
补丁: 0001-CLJ-1807-add-prefer-proto.patch