3

我正在尝试为我的应用程序制作一个特殊的附加组件。我需要在不编辑类文件的情况下覆盖类的某些方法。

这是一个方案:

class A
{
    public void method1()
    {
        // Do something here
    }

    public int method2()
    {
        // Do something
    }
}

现在从我的 B 类中,我想从 A 类中重写 method1 func,并强制 A 类使用我的新方法。

class B
{
    public void method1()
    {
        Do something
    }
}

我想在不编辑 A 类的情况下更新我的 A 类代码。那可能吗?

谢谢。

4

8 回答 8

4

使用class B extends A和覆盖您要更改的方法。你怎么必须使用类的实例Bnot A。像

class B extends A
{
    public void method1(){
      Do something
    }
}
A a = new B();
a.method1();
于 2012-04-06T11:50:57.310 回答
1

如果您使用A构造函数创建对象,则不会。您可以使用Bextend A,但您必须将对象实例化为new B()(即使您可以将它们声明A, 如 in A obj = new B())。

于 2012-04-06T11:52:36.980 回答
1

不,在像 Java 这样的语言中,这是不可能直接实现的。new A将始终在运行时创建 的实例A,而不是派生的B.

如果可能(也就是说,如果您控制所有实例化的代码A),您可以使用一些笨拙的解决方法来引入一种间接。例如,您可以有一个可配置的工厂来生产As(它会根据需要切换到在后台生产Bs)——这似乎是 Java 的方式。(您将不需要A直接使用所有代码构造,而是通过工厂。)

如果我没记错的话,您正在寻找的功能可以在 Objective C 中开箱即用 - 但在 Java 中不可用。

于 2012-04-06T12:01:53.290 回答
1

听起来像代理可以解决你的问题。看看cglib

Enhancer e = new Enhancer();
e.setSuperclass(A.class);
e.setCallback(new MyCallback());
A proxied = e.create();

这是 MyCallback 类的示例实现......

class MyCallback implements MethodInterceptor{
       public Object intercept(Object obj,
                                      Method method,
                                      Object[] args,
                                      MethodProxy proxy){
            Object stuffToReturn = null;
            if ("method1".equals(method.getName()) {
                 //Class B's method1 impl 
            } else {
                 //call the original method in class A
                 stuffToReturn  = method.invoke(proxy, args);
            }

            return stuffToReturn;   
        }
    }
于 2012-04-06T12:18:35.643 回答
0

通过继承,是的。只需更改 B 类定义:class B extends A

于 2012-04-06T11:50:33.733 回答
0

这没有任何意义。重写意味着重新定义从超类继承的方法。所以这里有一些解决方案:

  • B 必须扩展 A,然后您可以覆盖 A 的方法之一。给它与 A 中相同的签名,确保使用 @Override 注释。
  • A 有一些注入的依赖项:method1 和 method2 使用一些 tierce 对象 (C) 来完成工作,并将依赖项注入 A。然后 B 可以将 A 与适合其需要的自定义 C 对象一起使用。A 的大部分代码都不会那样改变。
于 2012-04-06T11:51:11.797 回答
0

实现这一点的一种方法是使用某种工厂实例来创建 A 类型的对象,而不是直接在代码中调用 A() 构造函数。然后,您的插件将需要提供并注册它自己的该工厂的实现,该工厂将创建 B 类的实例。这仅在插件在创建任何 A 实例之前被加载和初始化时才有效。

另一种方法是实现您自己的 ClassLoader 并在加载时使用它来修改 A 类的字节码。您可以搜索面向方面编程的工具来实现这一点。这只有在您可以控制 A 类的类加载过程时才有可能。

于 2012-04-06T12:04:21.290 回答
0

不,你不能这样做,如果不实际修改类就不可能修改类的行为,但是,有一个解决方法:

  1. B 应该从 A 继承。这是绝对需要的。A 不会改变,但它的子类可能会改变行为

  2. 覆盖 method1() 和 method2()

  3. 假设您有一个 A 类的对象。如果您将其转换为 B,它的行为将是您新的自定义行为。

于 2012-04-06T12:06:00.857 回答