reflection - 如何确定该类型实现了哪些协议(protocol)?

标签 reflection clojure clojurescript

给定某种类型或记录,我如何获取它实现的所有协议(protocol)?

假设我们有以下代码:

(defprotocol P1
  (op1 [this]))

(defprotocol P2
  (op2 [this]))

(defrecord R []
  P1
  (op1 [_] 1)
  P2
  (op2 [_] 2))

我需要的是一个执行类似操作的函数:

(all-protocols-for-type R) ;; => (P1 P2)

如果有一些与后端无关的东西那就太好了,因为我希望有一个适用于 Clojure 和 ClojureScript 的机制。

UPD:这样做的目的是内省(introspection)特定类型提供的功能。让我们说,通过这样做:

user> (supers (type {}))
#{clojure.lang.AFn clojure.lang.ILookup java.lang.Object java.util.Map clojure.lang.Seqable java.lang.Runnable clojure.lang.IPersistentCollection java.io.Serializable clojure.lang.IFn clojure.lang.APersistentMap clojure.lang.Associative java.util.concurrent.Callable clojure.lang.IKVReduce clojure.lang.Counted clojure.lang.IMeta clojure.lang.IMapIterable java.lang.Iterable clojure.lang.IPersistentMap clojure.lang.IEditableCollection clojure.lang.IObj clojure.lang.MapEquivalence clojure.lang.IHashEq}

我会知道我可以使用map作为函数(IFn),通过键查找值(Associative),甚至可以reduce-kv 就可以了(IKVReduce)。

最佳答案

这是在 Clojure 中无需做任何疯狂的事情就能得到的最接近结果:

(require '[clojure.set :as set])

(deftype EmptyType [])

(defrecord EmptyRecord [])

(defn all-protocols-for-type [t]
  (map (comp symbol (memfn getSimpleName))
       (set/difference (supers t)
                       (set/union (supers EmptyType)
                                  (supers EmptyRecord)))))

我使用特定的map只是为了获得与您在问题中给出的格式相同的输出;您应该根据需要修改映射函数。

基本上,您要问的是硬币的另一面this 。使用 deftypedefrecord 的协议(protocol)扩展存储有关类型的信息,并使用 extend-typeextend-protocol 存储协议(protocol)信息。

因此,如果您的所有扩展都直接在 deftypedefrecord 中完成,您可以使用我上面给出的方法获取给定类型的所有协议(protocol)。如果您的所有扩展都是使用 extend-typeextend-protocol 完成的,您可以使用 Alex 在其他问题的回答中给出的方法获取给定协议(protocol)的所有类型问题。但并没有一个好的方法可以在所有情况下都做到这两点。

关于reflection - 如何确定该类型实现了哪些协议(protocol)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35969848/

相关文章:

java - 如何使用 Java 反射将数组写入 XML 文件?

java - 使用反射加载 Build.getRadioVersion() 时出现 NoSuchMethodException

java - 使用默认方法从参数化接口(interface)中提取类

recursion - 使用 Spectre 递归地改变 map 中的值

clojurescript - 使用 js->clj 转换为 json 时如何保留数组中的关键字?

C# IsGenericType 没有按预期工作

java - 在 clojure 中调用需要类作为参数的 java 方法

clojure - 一种收集 Clojure Let 表达式的所有绑定(bind)的方法

javascript - 如何在 Clojurescript REPL 中显示生成的 JS?

clojure - 基座 : what data flow can you use to render a newly initialized empty list?