如何重写现有对象的方法?

2023-12-14

该对象是用以下命令创建的reify我需要重写它的方法之一。我发现的唯一方法是使用经典的 OO 装饰器和另一种用途reify。还有其他办法吗?


恐怕你必须创建一个装饰器,因为 Clojure 没有内置构造来默认将一个对象的行为委托给另一个对象(我认为这称为原型继承)。

但这并不意味着它必须很乏味 - 您可以使用宏和反射来自动化大部分工作。这是概念证明:

(defmacro decorator
  [clazz proto & fs]
  (let [proto-name (gensym "proto")
        methods (->> (clojure.reflect/reflect (resolve clazz))
                  :members
                  (filter #(instance? clojure.reflect.Method %))
                  (map (fn [{:keys [name parameter-types]}]
                         [name (count parameter-types)]))
                  set)
        to-delegate (clojure.set/difference
                      methods
                      (->> fs
                        (map (fn [[name params]]
                               [name (count params)]))
                        set))
        method-bodies
        (concat
          fs ;; these are our own definitions
          (for [[name n-params] to-delegate]
            (let [params (->> (range n-params)
                           (map #(gensym (str "x" %))))]
              `(~name [~@params]
                 (. ~proto-name (~name ~@params))) ;; this is where we delegate to the prototype
              )))]
    `(let [~proto-name ~proto]
       (proxy
         [~clazz] []
         ~@(->> method-bodies (group-by first) (sort-by first)
             (map (fn [[name bodies]]
                    `(~name ~@(for [[name & rest] bodies]
                                rest))))))
       )))

您将如何使用它:

(decorator
  java.util.Collection
  [:a :b :c]
  (size [] -1))
=> #object[user.proxy$java.lang.Object$Collection$4e41253d
        0x1eae8922
        "user.proxy$java.lang.Object$Collection$4e41253d@6abe9887"]

以及扩展:

(macroexpand-1 '(decorator
                  java.util.Collection
                  [:a :b :c]
                  (size [] -1)))
=>
(clojure.core/let
 [proto28109 [:a :b :c]]
 (clojure.core/proxy
  [java.util.Collection]
  []
  (add ([x028114] (. proto28109 (add x028114))))
  (addAll ([x028110] (. proto28109 (addAll x028110))))
  (clear ([] (. proto28109 (clear))))
  (contains ([x028118] (. proto28109 (contains x028118))))
  (containsAll ([x028116] (. proto28109 (containsAll x028116))))
  (equals ([x028119] (. proto28109 (equals x028119))))
  (hashCode ([] (. proto28109 (hashCode))))
  (isEmpty ([] (. proto28109 (isEmpty))))
  (iterator ([] (. proto28109 (iterator))))
  (parallelStream ([] (. proto28109 (parallelStream))))
  (remove ([x028117] (. proto28109 (remove x028117))))
  (removeAll ([x028115] (. proto28109 (removeAll x028115))))
  (removeIf ([x028111] (. proto28109 (removeIf x028111))))
  (retainAll ([x028112] (. proto28109 (retainAll x028112))))
  (size ([] -1))
  (spliterator ([] (. proto28109 (spliterator))))
  (stream ([] (. proto28109 (stream))))
  (toArray ([] (. proto28109 (toArray))) ([x028113] (. proto28109 (toArray x028113))))))

该实现生成一个proxy子句,但也可以用reify.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何重写现有对象的方法? 的相关文章

  • 懒惰的 juxt 函数有什么优点吗?

    在回答中一个问题 https stackoverflow com questions 10044254 is there a reverse map function关于一个使用相同参数映射多个函数的函数 A juxt 我想出了一个基本上采
  • 使用来自不同模块的 python 装饰器函数

    我想使用另一个模块中的函数作为装饰器 但我需要它来操作当前模块的全局命名空间 例如 我希望能够从这里开始 class SomeClass pass root SomeClass to this from othermodule import
  • Clojure:避免埃拉托斯特尼筛中的堆栈溢出?

    这是我在 Clojure 中实现的埃拉托斯特尼筛法 基于 SICP 流课程 defn nats from n iterate inc n defn divide p q zero rem q p defn sieve stream lazy
  • 使用装饰器将类方法包装在 try / except 中

    我有一个通用函数 可以将有关异常的信息发送到应用程序日志 我用exception handler来自类中方法的函数 传入并由应用程序调用的应用程序日志处理程序exception handler创建一个 JSON 字符串 该字符串是实际发送到
  • 是否有一个在线工具可以像 JSON 一样自动缩进和格式化 Clojure 代码?

    有很多在线工具可以获取 JSON 文本 并向您显示该文本的格式化和缩进格式 有些甚至更进一步 形成了一个漂亮的树状结构 http jsonviewer stack hu http jsonviewer stack hu 我们有类似的 Clo
  • pmap 和线程数

    user gt Runtime getRuntime availableProcessors 2 并评估这个例子 http clojuredocs org clojure core clojure core pmap example 684
  • fn 和 fn* 有什么区别?

    在 Clojure 中 fn 和 fn 有什么区别 当我在语法中引用使用 宏创建的函数时 我看到 fn 例如 在 REPL 中 user gt inc fn p1 342 343 auto clojure core inc p1 342 3
  • 在环形应用程序中捕获异常的惯用方法

    处理环形应用程序中的异常的惯用方法是什么 我想捕获异常并返回 500 页 我怎么做 我在下面的代码中使用了 Mustache 但是它不起作用 def my app try app wrap logger true wrap keyword
  • 如何在 Clojure 中更新原子的向量元素?

    我有一个矢量原子 我想更新一个本身就是地图的条目 def vector atom atom swap vector atom conj id 1 name myname 我该如何只更新该成员 在可变的 Java 领域的思维方式中 我会做这样
  • Clojure 函数 - 返回最后一条语句之前计算的值

    我有一些用 Clojure 编写的测试 这是一个简单的例子 defn test1 start server run pvt and expect PVT 0 stop server 我想返回 run pvt and expect 的结果 但
  • java与maven和eclipse中的clojure混合

    我创建了一个示例多语言程序 我有一个用java实现的传感器和一个机器人 以及用clojure实现的AI 我无法正确连接maven src main java clojuretest DistanceSensor java AI clj us
  • Clojure/Java:用于声音频谱分析的 Java 库? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个可以接受大量音频数据并返回给定频带内随时间变化的平均幅度的库 我已经在 comp dsp
  • Python 元类有什么用?

    元类可以用其他方式做不到的事情做什么 Alex Martelli 表示 有些任务如果没有元类就无法完成Python 元类与类装饰器 https stackoverflow com questions 1779372 python metac
  • 代理模式和装饰者模式的区别

    你能给出任何好的解释吗 Proxy and 装饰者 我看到的主要区别是 当我们假设Proxy uses 作品 and 装饰者 uses 聚合那么似乎很清楚 通过使用多个 一个或多个 装饰器您可以修改 添加功能到预先存在的实例 装饰 而Pro
  • 装饰器功能不起作用(意外标记)

    刚刚尝试在 React 中使用装饰器 import React from react import Fade from Transitions Fade import withVisible from withVisible withVis
  • Python 装饰器只是语法糖? [复制]

    这个问题在这里已经有答案了 可能的重复 了解 Python 装饰器 https stackoverflow com questions 739654 understanding python decorators 我对使用 Python 装
  • 获取调用表单的名称空间

    我想要一个宏this ns这样它就会返回调用它的位置的名称空间 例如 如果我有这段代码 ns nstest main require nstest core as nstest defn ns str x gt x getName name
  • Leiningen 在构建可用的 uberjar 时遇到问题

    我们正在尝试与 Leiningen 一起构建我们的 Clojure 项目 我们通过执行以下操作成功创建了 uberjar 前提条件 project clj 文件列出了依赖项 main my project core在项目 clj中 core
  • 如何在 Clojure 中链接 Promise

    在 Scala 中 您可以使用map and flatMap在未来的成功结果上运行函数 val x Future Int val y Future String x map toString 有没有比以下更好的 Clojure 类似物 de
  • Clojure 宏expand

    Why does macroexpand arm getHand getFinger 扩展到 arm getHand getFinger while macroexpand gt arm getHand getFinger 扩展到 getF

随机推荐

  • 检查字典是否是另一个字典的子集的递归函数

    我想递归地检查一本字典是否是另一本字典的子集 我们假设两个字典都有内置类型作为项目 我看到已经有一个很旧的线程了Python 检查一个字典是否是另一个较大字典的子集试图解决类似但不完全是的问题 因为那里的答案都不符合我的目的 所以我决定发布
  • Pandas 中的条件运行总和仅适用于所有先前的值

    假设我有以下数据框 df pd DataFrame Event A B A A B C B B A C Date 2019 01 01 2019 02 01 2019 03 01 2019 03 01 2019 02 15 2019 03
  • iOS 验证数字签名

    在我的应用程序中 我有一个公钥 表示为字符串 纯消息和数字签名 表示为 base64 编码字符串 使用 SHA256 进行哈希处理并使用 RSA 进行加密 现在 我需要验证数字签名 我试图执行以下操作 create SecKeyRef fr
  • 什么是 Setter 和 Getter?

    我对 Objective C 的 Setter 和 Getters 并没有真正的了解 有人可以为初学者提供一个好的指南吗 我注意到 当尝试访问另一个类中的变量时 这会发挥作用 我现在正在尝试这样做 我有两个类 比如说 A 和 B 我在 A
  • “${foo.bar}”和“#{foo.bar}”有什么区别?

    我可以通过表达式语言 EL 在 jsp 文件中使用 Java Bean 中的对象 因此我可以通过输入 foo bar 来获取我的值 但我也可以使用 foo bar 任何人都可以解释其中的差异或提供有意义信息的链接吗 这包含在JSP 2 1
  • Rails:指定没有值的参数给 link_to

    假设路线 map resources articles 你怎么得到这个 articles most popular using link to method 尝试了以下方法 link to articles path most popula
  • 防止 Flutter 中通过 video_player 使用的 ExoPlayer 发送垃圾邮件日志

    每当我在我的播放器中播放新文件时视频播放器我得到一长串日志 这使得查看我自己的日志变得更加困难 其中很多都包含记录值信息和嗨有没有办法让 video player 不那么喋喋不休 I ExoPlayerImpl 21717 Init d44
  • 避免重定向

    我正在尝试解析一个站点 用 ASP 编写 爬虫程序被重定向到主站点 但我想做的是解析给定的网址 而不是重定向的网址 有没有办法做到这一点 我尝试将 REDIRECT False 添加到settings py 文件中 但没有成功 以下是爬虫的
  • ASP.NET MVC3 RAZOR:从部分视图重定向

    我有两个部分视图 MyPopular 和 MyBlogs 有两个控制器 ArticleController cs 和 ThePopularController cs 这两个局部视图都包含按钮 最初 它在索引视图内呈现两个部分视图 在博客点击
  • 如何使用htaccess更改图片路径?

    我有一个包含图像的 html 文件 img src smilies happy gif 是否可以使用此路径重定向到另一个路径 htaccess 所以上面的例子就相当于 img src http static example com smil
  • 从 Excel 引用 Outlook 文件夹

    我创建了一个宏来读取 Outlook 电子邮件并将值和标题 发送的主题时间等 提取到 Excel 这之前可以工作 但现在提示错误 尝试的操作失败 找不到对象 该文件夹的位置是 收件箱 TIBCO 报告文件夹 错误提示在line Set ol
  • 带有填充 pkcs7 C++ 代码的 AES

    我需要一个使用 aes cbc256 和填充的字符串加密示例 在 C 中 gt 我正在 linux Ubuntu 上工作 PKCS7 请帮忙 对于以下代码 如何将 IV 设置为 0 并将键值设置为字符串值 我还想添加 pkcs7 填充 我正
  • Antlr4 从错误中恢复并继续解析直到 EOF

    我正在使用 Antlr 4 5 用 Ja va 编写 C 语法 当我处理具有预处理器指令的 C 源代码时 示例代码 using System using System Collections Generic using System Lin
  • Android:如何使用名称从资源中获取字符串?

    我希望在我的资源文件中为 UI 提供两种语言并为它们提供单独的字符串值res values strings xml
  • -[NSRunningApplication activateWithOptions:] 不工作

    我正在尝试创建一个程序来专注于某个应用程序 如果它已启动 这是我的代码 import
  • 如何验证(通过单元测试)错误堆栈是否打印在日志文件中?

    在继续对于这个答案我编写了一个单元测试来验证如果出现错误 堆栈将打印在日志文件中 测试方法 import org slf4j Logger import org slf4j LoggerFactory private final Logge
  • std::ostringstream 缓冲区的最大大小是多少?

    分配的大小是否基于动态分配的可用内存量 当我们达到这个限制时会发生什么 是否抛出异常或者覆盖内存的其他部分 或者它默默地停止写入缓冲区 的缓冲区std stringstream对象是一个包装器std string目的 因此 最大尺寸为std
  • 在全日历事件上重复时间

    我正在尝试在完整日历的某个时间制作一些重复事件 例如我希望事件发生于 2016年1月3日 直到 2016 年 1 月 7 日 这是我获取所有事件的代码
  • 多对多字段 django 添加双向关系

    我正在尝试实现一种允许用户关注另一个用户的功能 问题是当我将新用户添加到 关注者 时 关注另一个用户的用户也会添加到关注用户的以下列表中 例如 如果用户 a 关注用户 b 我将得到 view py def follow test reque
  • 如何重写现有对象的方法?

    该对象是用以下命令创建的reify我需要重写它的方法之一 我发现的唯一方法是使用经典的 OO 装饰器和另一种用途reify 还有其他办法吗 恐怕你必须创建一个装饰器 因为 Clojure 没有内置构造来默认将一个对象的行为委托给另一个对象