我有两个类ObjectA
和ObjectB
,它们都扩展了同一个类MasterObject
。我还有一个接口,其中包含我希望ObjectA
和ObjectB
实现的方法。在MasterObject
中找不到此方法。然后,我有一个类MasterObject
的字段,并希望访问ObjectA
和ObjectB
中的方法。这可能没有铸造吗?这是我的一些代码。
此外,我无法更改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();
似乎有效,但还有另一种方法可以在不进行投射的情况下执行此操作吗?有什么更清洁的吗?
答案 0 :(得分:3)
最后一个解决方案是创建一个实现AbstractMasterObject
的代理抽象类MyInterface
,这将允许ObjectA
和ObjectB
具有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
。这是一种快速简便的方法,可以使用MasterObject
和MyInterface
实例作为单个参考。缺点是Main
现在必须使用AbstractMasterObject
而不是MasterObject
。因此,它无法使用MasterObject
的任何其他子类。这根本不是问题,也可能是一个彻底的交易破坏者。实际上,它介于两者之间。
另一个选择是使用合成而不是继承。因此,ObjectA
和ObjectB
每个都有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
构造函数。然后维护MasterClass
和MyInterface
引用:
class Main {
MyInterface myInterface;
MasterObject masterObject;
public void method1(){
masterObject = new MasterObject();
myInterface = new ObjectA(masterObject);
myInterface.doSomething();
masterObject.someMasterObjectMethod();
}
}
此方法仅在ObjectA
不会覆盖MasterObject
方法或访问任何受保护成员时才有效。它也可能导致混淆,在MasterObject
和Main
中都引用相同的ObjectA
。如果两个类都可以更改MasterObject
的状态,那么您最终可能会遇到一些棘手的错误。另一方面,如果这些都不是问题,那么这可能是一个好方法。它将MyInterface
添加到Main
而不会中断MasterObject
,并间接使用MasterObject
来实现MyInterface
。
或者您可以完全隐藏MasterObject
Main
并仅通过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
完全一致。我认为如果这是遗留代码,这种方法最好,因为它是最少侵入性的。如果这是相对较新的代码,那么我在考虑这样的事情之前考虑其他策略。还有其他方法,但我认为这应该是一个很好的概述。无论如何,你应该退一步思考每个类之间的关系究竟是什么。这应该有助于指明你正确的方向。