java - 是否可以在 Java 中进行猴子补丁?

标签 java reflection monkeypatching

我不想讨论这种方法的优点,只要可能。我相信答案是“不”。但也许有人会让我大吃一惊!

假设您有一个核心小部件类。它有一个方法calculateHeight(),返回一个高度。高度太大 - 这导致按钮(比如说)太大。您可以扩展 DefaultWidget 来创建自己的 NiceWidget,并实现自己的 calculateHeight() 以返回更好的尺寸。

现在是一个库类 WindowDisplayFactory,以相当复杂的方法实例化 DefaultWidget。您希望它使用您的 NiceWidget。工厂类的方法如下所示:

public IWidget createView(Component parent) {
    DefaultWidget widget = new DefaultWidget(CONSTS.BLUE, CONSTS.SIZE_STUPIDLY);

    // bunch of ifs ...
    SomeOtherWidget bla = new SomeOtherWidget(widget);
    SomeResultWidget result = new SomeResultWidget(parent);
    SomeListener listener = new SomeListener(parent, widget, flags);

    // more widget creation and voodoo here

    return result;
}

就是这样。结果使 DefaultWidget 深入到其他对象的层次结构中。问题 - 如何让这个工厂方法使用我自己的 NiceWidget?或者至少让我自己的 calculateHeight() 在那里。理想情况下,我希望能够修补 DefaultWidget 以便它的 calculateHeight 做正确的事情......

public class MyWindowDisplayFactory {
    public IWidget createView(Component parent) {
        DefaultWidget.class.setMethod("calculateHeight", myCalculateHeight);
        return super.createView(parent);
    }
}

这是我可以在 Python、Ruby 等中执行的操作。不过,我发明了 setMethod() 这个名称。对我开放的其他选择是:

  • createView()方法的代码复制粘贴到我自己的继承自工厂类的类中
  • 与太大的小部件一起生活

工厂类无法更改 - 它是核心平台 API 的一部分。我尝试对返回的结果进行反射以获取(最终)添加的小部件,但它向下有几个小部件层,并且在某个地方它被用来初始化其他东西,导致奇怪的副作用。

有什么想法吗?到目前为止,我的解决方案是复制粘贴作业,但这是一种逃避,需要在升级到新版本平台时跟踪父工厂类的更改,我很想听听其他选项。

最佳答案

也许您可以使用面向方面的编程来捕获对该函数的调用并返回您自己的版本?

Spring 提供了一些 AOP 功能,但也有其他库也可以。

关于java - 是否可以在 Java 中进行猴子补丁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/381226/

相关文章:

python - 我如何猴子修补另一个包的管理类?

python - Django为 "Fully Loaded"后如何运行任意代码

java - 如何格式化我的文本?

java - 谁处理 RuntimeException?

java - 暂停按钮java

java - 如何使用类型化参数从 Java callablestatement 调用 Oracle 过程?

c# - 使用 Entity Framework 4.0 中的上下文确定实体的主键

c++ - c++11 中的 typeid(T).name() 替代方案?

c# - 如何通过反射调用带有枚举(enum)参数的方法?

ruby-on-rails - 单个对象上的猴子补丁方法