覆盖实例化的Java对象中的方法

时间:2010-10-06 18:23:07

标签: java oop methods override

我想覆盖一个由我无法控制的工厂交给我的对象中的方法。

我的具体问题是我想覆盖套接字对象 getInputStream getOutputStream 来执行 wire登录

一般问题如下:

public class Foo {
    public Bar doBar() {
        // Some activity
    }
}

我想采用实例化的Foo并将doBar替换为我自己的Bar doBar() { // My own activity return original.doBar(); } ,其工作原理如下:

{{1}}

对于Socket,我将返回一个 InputStream OutputStream ,它们通过记录来拦截数据。

9 个答案:

答案 0 :(得分:20)

由于Java使用基于类的OO,因此这是不可能的。你可以做的是使用decorator pattern,即为返回包装流的对象写一个包装器。

答案 1 :(得分:13)

我认为有一种方法可以达到你想要的效果。我看到它在带有按钮的摇摆中使用,以允许程序员在按下按钮时执行某些操作。

说你有你的Foo课程:

public class Foo {
  public Bar doBar() {
    // Some activity
  }
}

然后你有一个跑步者类或类似的东西。您可以在实例化时覆盖doBar()方法,它只会影响该特定对象。

该课程可能如下所示:

public class FooInstance{
  Foo F1 = new Foo(){
    public Bar doBar(){
      //new activity
    }
  }

  Foo F2 = new Foo();

  F1.doBar(); //does the new activity
  F2.doBar(); //does the original activity found in the class
}

我不完全确定会为你做什么,但也许它会让你朝着正确的方向前进。如果没有别的东西可以覆盖课外的方法,也许这会对你有帮助。

答案 2 :(得分:6)

您无法替换现有对象中的方法 - 您无法更改现有对象的类型。

您可以创建另一个类的新实例,委托到现有实例,但这也有局限性。

在你的真实世界的情况下你是不是可以简单地单独调用来包装套接字返回的流?你能提供更多细节吗?

答案 3 :(得分:1)

使用装饰器是正确的方法:

一些与套接字要求非常相似的代码在这里:

http://www.javaspecialists.eu/archive/Issue058.html

答案 4 :(得分:0)

我不确定这是否可行。您是否考虑过创建自己的类,将工厂作为成员返回的对象,然后为该类编写doBar()方法。

答案 5 :(得分:0)

你无法在java中动态更改对象。

通过将Foo包装到另一个类似的对象中,您可以拥有自己想要的东西,该对象会将每次调用委托给Foo并在同一日志中委托您想要的所有内容。 (见Proxy

但是如果你想做日志记录,也许方面是更好的选择。 (见AspectJ

答案 6 :(得分:0)

两个选项:

  1. easy:如果您实现了Foo接口,则可以使用Dynamic proxy添加新功能。
  2. 更多工作:你所拥有的是AOP的“周围”建议 - 你可以使用任何现有的AOP工具来实现这一目标。如果您已经使用它,Spring Framework可以为您完成。

答案 7 :(得分:0)

另一个与代理相关的解决方案:您可以使用Aspects覆盖给定对象上的方法,而无需自己进行子类化。这对于日志记录尤其适用且常见。这个例子使用了spring-aop。

CoordinatorLayout

答案 8 :(得分:0)

如果Socket是一个接口,那么你可以创建一个动态代理。以下是一个例子。我把它放在这里,以防其他人需要这样做,目标实例是一个接口的实例。

这对Socket不起作用的主要原因是因为java.lang.reflect.Proxy.newProxyInstance需要第二个参数的接口数组,所以类不会在这里工作。因此,对于此示例,我必须创建一个名为ParentInterface的接口,它只有三种打印方法。

public class Parent implements ParentInterface {

    @Override
    public void print1() {
        System.out.println("parent 1");
    }

    @Override
    public void print2() {
        System.out.println("parent 2");
    }

    @Override
    public void print3() {
        System.out.println("parent 3");
    }

    public static void main(String[] args) {
        Parent originalInstance = new Parent();
        ParentInterface proxied = (ParentInterface) java.lang.reflect.Proxy.newProxyInstance(
                Parent.class.getClassLoader(),
                new Class[]{ParentInterface.class},
                new ParentProxy(originalInstance));

        proxied.print1();
        proxied.print2();
        proxied.print3();

    }

    static class ParentProxy implements InvocationHandler {

        final Object realObject;

        public ParentProxy(Object real) {
            realObject = real;
        }

        @Override
        public Object invoke(Object target, Method m, Object[] args) throws Throwable {
            try {
                if (m.getName().equals("print2")) {
                    print2();
                    return null;
                } else {
                    return m.invoke(realObject, args);
                }
            } catch (java.lang.reflect.InvocationTargetException e) {
                throw e.getTargetException();
            }
        }

        public void print2() {
            System.out.println("wrapper 2");
        }

    }

}