Java继承 - 使用相同方法的两个类

时间:2017-07-07 17:53:11

标签: java inheritance casting

我有两个类ObjectAObjectB,它们都扩展了同一个类MasterObject。我还有一个接口,其中包含我希望ObjectAObjectB实现的方法。在MasterObject中找不到此方法。然后,我有一个类MasterObject的字段,并希望访问ObjectAObjectB中的方法。这可能没有铸造吗?这是我的一些代码。

此外,我无法更改MasterObject课程。

public interface MyInterface{
    void doSomething();
}

class ObjectA extends MasterObject implements MyInterface {

    @Override
    public void doSomething(){
        //...
    }
}

class ObjectB extends MasterObject implements MyInterface {
    @Override 
    public void doSomething(){
        //...
    }
}

class Main {
    MasterObject mObj;

    public void method1() {
        mObj = new ObjectA();
        mObj.doSomething();
    }

    public void method2() {
        mObj = new ObjectB();
        mObj.doSomething(); //runs code from ObjectB class
    }
}

现在这显然是在抛出一些编译器问题。 (无法解析方法doSomething())。

像这样投射:((ObjectA) mObj).doSomething();似乎有效,但还有另一种方法可以在不进行投射的情况下执行此操作吗?有什么更清洁的吗?

4 个答案:

答案 0 :(得分:3)

最后一个解决方案是创建一个实现AbstractMasterObject的代理抽象类MyInterface,这将允许ObjectAObjectB具有MasterObject的完整功能}和MyInterface如果他们扩展AbstractMasterObject

这可以这样做:

public abstract class AbstractMasterObject extends MasterObject implements MyInterface{

}

然后你可以这样声明你的对象:

AbstractMasterObject a = new ObjectA();
AbstractMasterObject b = new ObjectB();

答案 1 :(得分:2)

最干净的方法是将接口声明为类型:

MyInterface mObj;

您可以使用相同的方式使用具体类实例化对象:

mObj = new ObjectA();
...
mObj = new ObjectB();

唯一的限制是 - 没有强制转换 - 您将只能调用doSomething方法,因为它是接口中定义的唯一方法。如果您打算只使用这种方法,那么就可以了。

答案 2 :(得分:1)

问题是班级MasterObject没有实现接口MyInterface,尽管他的孩子也这样做。

解决方案是实现界面:

MyInterface mObj;
mObj = new ObjectA();

答案 3 :(得分:1)

这里有几个选项,有些已被提及。您已经提到,您无法将界面添加到MasterObject,并且互动比doSomething更复杂。任何其他约束都可能决定哪种最适合你。

第一个选项是像Craig建议的那样做,并创建中间AbstractMasterObject以扩展MasterObject并实现MyInterface。这是一种快速简便的方法,可以使用MasterObjectMyInterface实例作为单个参考。缺点是Main现在必须使用AbstractMasterObject而不是MasterObject。因此,它无法使用MasterObject的任何其他子类。这根本不是问题,也可能是一个彻底的交易破坏者。实际上,它介于两者之间。

另一个选择是使用合成而不是继承。因此,ObjectAObjectB每个都有MasterObject的实例,而不是扩展它。然后他们使用该引用来访问MasterClass行为(为简洁起见,我只是显示ObjectA):

class ObjectA implements MyInterface {

     private masterObject masterObject; 

     public ObjectA(MasterObject masterObject){
       this.masterObject = masterObject;
    }
    @Override
    public void doSomething(){ /* Implementation */ }

 }

从这里开始,有一些不同的策略可以将其纳入Main。您可以在MasterClass中引用Main并将其传递给ObjectA构造函数。然后维护MasterClassMyInterface引用:

class Main {
   MyInterface myInterface;
   MasterObject masterObject;

   public void method1(){
      masterObject = new MasterObject();
      myInterface = new ObjectA(masterObject);

      myInterface.doSomething();
      masterObject.someMasterObjectMethod();

   }
}

此方法仅在ObjectA不会覆盖MasterObject方法或访问任何受保护成员时才有效。它也可能导致混淆,在MasterObjectMain中都引用相同的ObjectA。如果两个类都可以更改MasterObject的状态,那么您最终可能会遇到一些棘手的错误。另一方面,如果这些都不是问题,那么这可能是一个好方法。它将MyInterface添加到Main而不会中断MasterObject,并间接使用MasterObject来实现MyInterface

或者您可以完全隐藏MasterObject Main并仅通过MyInterface进行互动。为此,您可以在getMasterObjectMyInterface。或者,您可以向MyInterface添加专门与Main如何与之交互的方法。我认为像这样的方法是最干净的,但它涉及更改大多数代码。如果这主要是新的开发,那么重构可能是值得的。如果它的代码较旧,那么我赞成采用侵入性较小的方法。

另一种选择是从略微不同的方向来解决这个问题。您完全按照定义的类使用这些类。区别在于Main同时指向同一个实例的MasterObjectMyInterface引用:

class Main {

   private MasterObject masterObject;
   private MyInterface myInterface;

   public void method1(){

       ObjectA objectA = new ObjectA();
       masterObject = objectA; // Legal because ObjectA extends MasterObject
       myInterface = objectA; // Legal because ObjectA implements MyInterface

       myInterface.doSomething(); // This does ObjectA's implementation
       masterObject.someMasterObjectMethod();

   }
}

因此,对于Main来说,同一个实例的执行情况与MyInterfaceMasterObject完全一致。我认为如果这是遗留代码,这种方法最好,因为它是最少侵入性的。如果这是相对较新的代码,那么我在考虑这样的事情之前考虑其他策略。还有其他方法,但我认为这应该是一个很好的概述。无论如何,你应该退一步思考每个类之间的关系究竟是什么。这应该有助于指明你正确的方向。