gpt4 book ai didi

object - 在 clojure 中为对象的特定实例创建代理

转载 作者:行者123 更新时间:2023-12-05 00:01:34 26 4
gpt4 key购买 nike

我正在尝试创建一个代理对象,它使用闭包(let/proxy)为对象的某些方法添加一些功能我可以做这件事,不幸的是我不得不重新编写原始对象的所有方法o我得到一个 UnsupportedOpretationException 这是一个例子:
;;真实的对象

(def realcon (java.sql.DriverManager/getConnection "jdbc:h2:tcp://localhost:9092/test"))


(def con
(let [msg "FG>"
xcon rcon]
(proxy [java.sql.Connection] []
(createStatement []
(println msg) ;; access to closure context !
(.createStatement xcon)))))

(def stmt (.createStatement con))
;;output FG>

(def rs (.executeQuery stmt "select count(*) from serie_sat"))

如果我从 java.sql.Connection 调用任何其他方法,我会得到 UnsupportedOperationException 我可以手动代理所有方法,但可能有更好的方法!

谢谢

最佳答案

这是使用 reify 的替代方法而不是 proxy因为,根据 docs ,它“在所有限制条件不禁止的情况下都是优选的”。

(defmacro override-delegate
[type delegate & body]
(let [d (gensym)
overrides (group-by first body)
methods (for [m (.getMethods (resolve type))
:let [f (-> (.getName m)
symbol
(with-meta {:tag (-> m .getReturnType .getName)}))]
:when (not (overrides f))
:let [args (for [t (.getParameterTypes m)]
(with-meta (gensym) {:tag (.getName t)}))]]
(list f (vec (conj args 'this))
`(. ~d ~f ~@(map #(with-meta % nil) args))))]
`(let [~d ~delegate]
(reify ~type ~@body ~@methods))))


;; Modifying your example slightly...
(def realcon (java.sql.DriverManager/getConnection "jdbc:h2:tcp://localhost:9092/test"))
(def con
(let [msg "FG>"]
(override-delegate java.sql.Connection realcon
(createStatement [this]
(println msg)
(.createStatement realcon)))))
override-delegate宏期望正文包含 reify您希望覆盖的方法的规范。您未覆盖的任何内容都将在委托(delegate)上调用。全部 reify宏生成的规范将包括每个方法的参数和返回值的类型提示。

我的实现有一个警告:它只检查 body 中的方法名称。 ,忽略重载方法的参数数量/类型。所以在上面的例子中, java.sql.Connection接口(interface)提供多个 createStatement重载,不会为 con 定义接受参数的重载。 .扩展宏以解决重载问题并不太难,但是当我需要这种行为时,我通常必须覆盖所有这些行为。

关于object - 在 clojure 中为对象的特定实例创建代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9086926/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com