如何重写现有对象的方法? [英] How to override a method of an existing object?

查看:13
本文介绍了如何重写现有对象的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该对象是用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完成。

这篇关于如何重写现有对象的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆