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

Java继承-使用相同方法的两个类,java,inheritance,casting,Java,Inheritance,Casting,我有两个类,ObjectA和ObjectB,它们都扩展了相同的类MasterObject。我还有一个接口,其中包含一个我希望ObjectA和ObjectB实现的方法。在主对象中找不到此方法。然后我有一个类,它有一个类型为MasterObject的字段,并希望访问ObjectA和ObjectB中的方法。这不需要铸造就可以吗?这是我的一些代码 此外,我无法更改主对象类 public interface MyInterface{ void doSomething(); } class Obj

我有两个类,
ObjectA
ObjectB
,它们都扩展了相同的类
MasterObject
。我还有一个接口,其中包含一个我希望
ObjectA
ObjectB
实现的方法。在
主对象
中找不到此方法。然后我有一个类,它有一个类型为
MasterObject
的字段,并希望访问
ObjectA
ObjectB
中的方法。这不需要铸造就可以吗?这是我的一些代码

此外,我无法更改
主对象

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()
似乎很有效,但有没有其他方法可以不用强制转换来实现这一点?有更干净的吗?

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

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

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

唯一的限制是,在没有强制转换的情况下,您只能调用
doSomething
方法,因为它是接口中定义的唯一方法。如果您只打算使用此方法,那就应该这样做。

问题在于类
MasterObject
没有实现接口
MyInterface
,尽管他的孩子实现了

解决方案是实现接口:

MyInterface mObj;
mObj = new ObjectA();

最后一个解决方案是创建一个代理抽象类
AbstractMasterObject
,该类实现
MyInterface
这将允许
ObjectA
ObjectB
拥有
MasterObject
MyInterface
的全部功能,如果它们扩展
AbstractMasterObject

可以这样做:

public abstract class AbstractMasterObject extends MasterObject implements MyInterface{

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

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

您在这里有一些选择,其中一些已经提到。您已经提到,不能将接口添加到
主对象中,并且交互比
doSomething
更复杂。任何其他约束都可能决定哪一个最适合您

第一个选项是按照Craig的建议,创建中间的
AbstractMasterObject
,以扩展
MasterObject
,并实现
MyInterface
。这是一种快速简便的方法,可以创建一个既是
MasterObject
又是
MyInterface
实例的引用。缺点是
Main
现在必须使用
AbstractMasterObject
而不是
MasterObject
。因此它不能使用
MasterObject
的任何其他子类。这可能根本不是问题,也可能完全破坏了交易。实际上,它介于两者之间

另一种选择是使用组合而不是继承。因此
ObjectA
ObjectB
都有
MasterObject
的实例,而不是扩展它。然后,他们使用该引用访问
MasterClass
行为(为了简单起见,我只是展示
ObjectA
):

从这里开始,有几种不同的策略可以将其合并到
Main
中。您可以在
Main
中引用
MasterClass
,并将其传递给
ObjectA
构造函数。然后维护
MasterClass
MyInterface
参考:

class Main {
   MyInterface myInterface;
   MasterObject masterObject;

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

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

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

或者您可以完全从
Main
隐藏
MasterObject
,并且仅通过
MyInterface
进行交互。要做到这一点,您只需从
getMasterObject
MyInterface
。或者,您可以向
MyInterface
中添加专门与
Main
如何与之交互相关的方法。我认为这样的方法是最干净的,但它需要修改最多的代码。如果这主要是新的开发,那么重构可能是值得的。如果是较旧的代码,那么我倾向于采用侵入性较小的方法

另一个选择是从稍微不同的方向来实现这一点。您完全按照定义的方式使用这些类。不同之处在于,
Main
同时有一个
MasterObject
MyInterface
引用指向同一个实例:

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
,同一个实例作为
MyInterface
MasterObject
执行是完全巧合的。我认为如果这是遗留代码,这种方法将是最好的,因为它是入侵性最小的。如果这是一个比较新的代码,那么我会考虑其他策略,然后诉诸这样的事情。还有其他方法,但我认为这应该是一个很好的概述。不管怎样,您都应该后退一步,思考这些类之间的关系到底是什么。这将帮助您找到正确的方向。

您能够更改
主对象
类吗?@CraigR8806不,我不能。谢谢。这似乎有效。我尽可能地简化了我的问题,但事实是,有几种方法是共享的,我需要添加到接口中。代理是更好的方法
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();

   }
}