2

我正在开发一个应用程序,它建立在另一个开发人员编写的类上(我没有源代码)。

我希望使用该类的所有功能,但也希望使用其他功能对其进行扩展。通常为了实现这一点,我会定义一个接口 ( MyInterface ) 并在实现MyInterface时从我自己的 ( MyClass )扩展外部类 ( TheyClass ) 。

public interface TheirClassInterface {
    public void theirMethod1();
    public void theirMethod2();
}

public class TheirClass implements TheirClassInterface {
    public void theirMethod1() { ... }
    public void theirMethod2() { ... }
}

public class TheirOtherClass {
    public void theirOtherMethod1(TheirClassInterface o) { ... }
}

public interface MyInterface() {
    public void myMethod1();
}

public class MyClass extends TheirClass implements MyInterface {
    public void myMethod1() { ... }
}

public class MyNewClass extends MyClass {
    public void MyNewClassMethod() { ... }
}

问题因以下事实而变得复杂:

  1. 我现在希望创建一个新类(MyNewClass ),它为MyClass添加附加功能,但我不希望我的代码依赖于TheyClass
  2. 我希望能够将我的类用作TheyOtherClass方法的参数。

为了解决这个问题,我重构了我的代码,改为使用组合而不是继承并实现TheyClassInterface。这可行,但需要我实现许多方法并将它们委托给theirClassObject(实际上,它们的ClassInterface包含大量方法)。

public interface TheirClassInterface {
    public void theirMethod1();
    public void theirMethod2();
}

public class TheirClass implements TheirClassInterface {
    public void theirMethod1() { ... }
    public void theirMethod2() { ... }
}

public class TheirOtherClass {
    public void theirOtherMethod1(TheirClassInterface o) { ... }
}

public interface MyInterface() {
    public void myMethod1();
}

public class MyClass implements TheirClassInterface, MyInterface {
    private TheirClass theirClassObject;

    public void myMethod1() { ... }
    public void theirMethod1() { theirClassObject.theirMethod1(); }
    public void theirMethod2() { theirClassObject.theirMethod2(); }
}

public class MyNewClass extends MyClass {
    public void MyNewClassMethod() { ... }
}

我的问题是我的方法在这种情况下是否合适,是否可以改进,因为在我看来,我的代码使用过多的委托来完成工作。

非常感谢任何人对此提供的任何指导。

丹尼

4

3 回答 3

1

首先,由于 java 是一种强类型的单继承语言,您无法逃避委托。

但是你可以避免编写大量的委托代码,通过使用代理和反射的肮脏小技巧。代码如下

public interface Interface1 {
    void m1();
}
public interface Interface2 {
    void m2();
}
public class Class1 implements Interface1 {
    public void m1() {
        System.out.println(1);
    }

}
public class Class2 implements Interface2 {
    public void m2() {
        System.out.println(2);
    }
}
public interface MixinInterface extends Interface1, Interface2 {

}

这就是魔法发生的方式

package j.with.pseudo.multiple.inheritance;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MixinBuilder {

    public static Object buildMixed(Class _interface, Object... impls){
        InvocationHandler h = new MixinHandler(_interface.getInterfaces(), impls);
        return Proxy.newProxyInstance(MixinBuilder.class.getClassLoader(), 
            new Class[]{_interface}, h);
    }

    public static void main(String[] args) {
        Class1 o1 = new Class1();
        Class2 o2 = new Class2();
        MixinInterface almost_like_multiple_inheritance_guy = 
            (MixinInterface) buildMixed(MixinInterface.class, o1, o2);
        almost_like_multiple_inheritance_guy.m1();
        almost_like_multiple_inheritance_guy.m2();
    }

    private static class MixinHandler implements InvocationHandler{

        private Class[] interfaces;
        private Object[] impls;

        public MixinHandler(Class[] interfaces, Object[] impls) {
            this.interfaces = interfaces;
            this.impls = impls;
        }

        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            int i=0;
            for(Class _interface : interfaces){
                if(method.getDeclaringClass().isAssignableFrom(_interface)){
                    return method.invoke(impls[i], args);
                }
                i++;
            }
            // TODO Auto-generated method stub
            throw new RuntimeException("Method not found: "+method);
        }

    }
}

很酷吧?:-)

于 2012-08-03T15:23:44.553 回答
0

Many thanks for the answers so far. I've come up with a solution which I think seems reasonable and allows me to fully encapsulate the foreign class.

At the moment I've returned to the method discussed in the first block of code (repeated and extended below) and am now implementing my MyInterface interface for MyNewClass and delegating all interface operations to a composed object. The object to delegate to is decided at runtime by calling a static method on a Factory.

public interface TheirClassInterface {
    public void theirMethod1();
    public void theirMethod2();
}

public class TheirClass implements TheirClassInterface {
    public void theirMethod1() { ... }
    public void theirMethod2() { ... }
}

public class TheirOtherClass {
    public void theirOtherMethod1(TheirClassInterface o) { ... }
}

public interface MyInterface() {
    public void myMethod1();
}

public class MyClass extends TheirClass implements MyInterface {
    public void myMethod1() { ... }
}

public class MyNewClass implements MyInterface {
    private MyInterface myObject;

    public MyNewClass() {
        myObject = MyClassFactory.createMyClass();
    }

    public void myMethod1() {
        myObject.myMethod();
    }

    public void MyNewClassMethod() { ... }
}

Once again, thanks for the ideas. I'm now going to look into them all and see if I can use them to improve my code.

Cheers,

Danny

于 2012-08-03T15:53:32.497 回答
0

如果你正在扩展一个类,你就不能不依赖它;就像有一个 的定义Human,它不依赖于 的定义Mammal,您的 optinos 将重写父级中的所有内容,或者依赖于它。

于 2012-08-03T15:35:26.593 回答