如何在不将我的类绑定到特定实现的情况下获得实现继承的好处?

时间:2012-08-03 13:14:06

标签: java inheritance refactoring coupling

我正在开发一个基于另一个开发人员编写的类的应用程序(我没有源代码)。

我希望使用所述类的所有功能,但也希望使用其他功能扩展它。通常为了达到这个目的,我会定义一个接口( MyInterface )并从我自己的( MyClass )扩展外部类( TheirClass )实现 MyInterface

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 添加了额外的功能,但我不希望我的代码依赖于他们的类的。
  2. 我希望能够将我的类用作 TheirOtherClass 方法的参数。

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

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() { ... }
}

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

非常感谢任何人都能给予的任何指导。

丹尼

3 个答案:

答案 0 :(得分: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);
        }

    }
}

非常酷吧? : - )

答案 1 :(得分:0)

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

答案 2 :(得分:0)

非常感谢到目前为止的答案。我想出了一个我认为合理的解决方案,并允许我完全封装外国类。

目前我已经回到第一个代码块中讨论的方法(下面重复和扩展),现在正在为 MyNewClass 实现我的 MyInterface 接口将所有接口操作委托给组合对象。委托的对象在运行时通过调用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() { ... }
}

再次感谢您的想法。我现在要调查它们,看看我是否可以使用它们来改进我的代码。

干杯,

丹尼