Jon*_*Jon 17 java oop inheritance instanceof
我在大学的某个阶段被告知(并且随后在十几个地方读过),使用instanceof应仅用作"最后的手段".考虑到这一点,是否有人能够告诉我以下代码是否是最后的手段.我已经看过堆栈溢出但是找不到类似的场景 - 也许我错过了它?
private void allocateUITweenManager() {
for(GameObject go:mGameObjects){
if (go instanceof GameGroup) ((GameGroup) go).setUITweenManager(mUITweenManager);
}
}
Run Code Online (Sandbox Code Playgroud)
哪里
mGameObjects是一个数组,只有一些是GameGroup类型GameGroup是抽象类的子类GameObject.GameGroup使用UITweenable具有方法的接口setUITweenManager()GameObject 不使用界面 UITweenable我想我可以同样(也可能应该)替换GameGroup上面的代码UITweenable- 我会问同样的问题.
还有另一种方法可以避免这种情况instanceof吗?这段代码不能失败,因此(我认为,对吧?),但鉴于坏消息instanceof似乎得到了,我是否已经在我instanceof在这里使用的线路上某处犯了一些OOP的主要罪?
提前致谢!
我Visitor pattern在大学的Compiler课程中学到了,我认为它可能适用于你的场景.考虑以下代码:
public class GameObjectVisitor {
public boolean visit(GameObject1 obj1) { return true; }
.
.
// one method for each game object
public boolean visit(GameGroup obj1) { return true; }
}
Run Code Online (Sandbox Code Playgroud)
然后你可以在这样的GameObject界面中放一个方法:
public interface GameObject {
.
.
public boolean visit(GameObjectVisitor visitor);
}
Run Code Online (Sandbox Code Playgroud)
然后每个GameObject实现此方法:
public class GameGroup implements GameObject {
.
.
.
public boolean visit(GameObjectVisitor visitor) {
visitor.visit(this);
}
}
Run Code Online (Sandbox Code Playgroud)
当你具有复杂的继承层次结构时,这特别有用GameObject.对于您的情况,您的方法将如下所示:
private void allocateUITweenManager() {
GameObjectVisitor gameGroupVisitor = new GameObjectVisitor() {
public boolean visit(GameGroup obj1) {
obj1.setUITweenManager(mUITweenManager);
}
};
for(GameObject go:mGameObjects){
go.visit(gameGroupVisitor);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
您可以在这里做两件主要的事情来缓解这个特定的 实例instanceof。(双关语?)
按照我最初的答案建议的操作,并将您的目标方法移至您正在迭代的类。在这种情况下,这并不理想,因为该方法对父对象没有意义,并且会像 Ted 所说的那样造成污染。
将正在迭代的对象的范围缩小到仅熟悉目标方法的对象。我认为这是更理想的方法,但在当前的代码形式中可能行不通。
就我个人而言,我instanceof像躲避瘟疫一样避免,因为这让我觉得我完全错过了一些东西,但有时这是必要的。如果您的代码是这样布局的,并且您无法缩小正在迭代的对象的范围,那么instanceof可能会工作得很好。但这看起来是一个很好的机会,可以了解多态性如何使您的代码在未来更易于阅读和维护。
我将原来的答案留在下面,以保持评论的完整性。
/编辑
就我个人而言,我认为这不是使用instanceof. 在我看来,您可以利用一些多态性来实现您的目标。
您是否考虑过制作setUITweenManager(...)一种方法GameObject?这样做有意义吗?
如果它确实有意义,您可以让默认实现不执行任何操作,并让您GameGroup重写该方法来执行您希望它执行的操作。此时,您的代码可能如下所示:
private void allocateUITweenManager() {
for(GameObject go:mGameObjects){
go.setUITweenManager(mUITweenManager);
}
}
Run Code Online (Sandbox Code Playgroud)
这是实际的多态性,但我不确定这是否是适合您当前情况的最佳方法。如果可能的话,迭代对象Collection会更有意义。UITweenable