说我有这样的通用数组:
ArrayList<Fruit> fruits = new ArrayList<Fruit>();
然后我添加了许多不同的水果,这些水果都延伸了类水果,并循环通过它们
for (Fruit f : fruits) {
}
如果水果是香蕉,我想检查它是多么圆,所以......
for (Fruit f : fruits) {
if (f instanceof Bannana)
f.checkHowRoundBannanaIs();
}
我必须将checkHowRoundBannnaIs()
方法放在水果类中,即使水果可能不是香蕉,因为如果它不在水果类中,我就不能使用f上的函数,否则我得到一个未定义的方法错误(或类似的东西)。
对于一种或两种方法来说这很好,但过了一段时间它会让这个类变得笨重而且难看。所以我的问题是,我如何向类中添加方法并在超类的for-style循环中使用它们?
答案 0 :(得分:3)
所以我的问题是,如何向类中添加方法并在超类的for-style循环中使用它们?
简短回答,你不能真的。
如果你想调用for循环体中的方法,instanceof
和向下转换是我能想到的唯一方法:
for (Fruit f : fruits) {
if (f instanceof Banana)
((Banana) f).checkHowRoundBananaIs();
// ...
}
instanceof
和向下投射通常被认为是不好的做法。为避免这种情况,您可以实施visitor pattern。以下是您需要采取的步骤:
创建一个这样的访问者界面:
interface FruitVisitor {
void visit(Banana banana);
void visit(Apple apple);
}
让所有水果接受访客:
abstract class Fruit {
// ...
public abstract void accept(FruitVisitor fv);
}
class Banana extends Fruit {
public void accept(FruitVisitor fv) {
fv.visit(this);
}
public void checkHowRoundBananaIs() { ... }
}
创建一个访问者,为每种类型的水果采取适当的操作,并将其作为参数传递给列表中每个水果的accept
方法:
FruitVisitor fv = new FruitVisitor() {
public void visit(Banana banana) {
banana.checkHowRoundBananaIs();
}
public void visit(Apple apple) {
// ...
}
};
for (Fruit f : fruits)
f.accept(fv);
答案 1 :(得分:2)
与您尝试过的方法最相似的技巧是将f
转换为Banana
:
if(f instanceof Bannana)
((Banana)f).checkHowRoundBannanaIs()
我不确定这是否真的是你想要的。
答案 2 :(得分:1)
您不必将checkHowRoundBanannaIs()
放入Fruit
课程。一旦您知道f
是Banana
的实例,就可以安全地将f
向下转换为类型Banana
。现在您已拥有Banana
个实例,您可以调用任何Banana
特定方法(包括checkHowRoundBananaIs()
。
for(final Fruit f : fruits)
{
if(f instanceof Banana)
{
final Banana b = (Banana) f;
b.checkHowRoundBananaIs();
}
}
答案 3 :(得分:1)
看到你已经在检查它是否是香蕉,你可以将它投入香蕉然后进行检查..
for(fruit f : fruits)
{
if(f instanceof Banana) {
Banana b = (Banana)f;
b.checkHowRoundBananaIs()
}
}
答案 4 :(得分:0)
for(fruit f : fruits)
{
if(f instanceof Bannana)
f.checkHowRoundBannanaIs()
}
...这不是“超级类的for-style循环”。从逻辑上讲。
ASA你做instanceof Bannana
你必须导入Bannana
(虽然我想你想要输入Banana)。导入后,没有理由不将f
投射到Banana
。一旦你这样做,你就可以访问Banana
的所有方法。
简而言之,通常您不会进行obj1 instanceof XXX
检查,除非您确实要将obj1
用作XXX
。
当然,有更好的方式,如访问者模式(请参阅其他帖子)或将功能提取到超类。虽然我猜你已经接受了你的设计有些问题而且你不想修复它。