Java 如何向类添加方法并在其超类的for样式循环中使用它们?
假设我有这样一个通用数组:Java 如何向类添加方法并在其超类的for样式循环中使用它们?,java,oop,generics,Java,Oop,Generics,假设我有这样一个通用数组: ArrayList<Fruit> fruits = new ArrayList<Fruit>(); interface FruitVisitor { void visit(Banana banana); void visit(Apple apple); } 如果水果是香蕉,我想看看它有多圆,所以 for (Fruit f : fruits) { if (f instanceof Bannana) f
ArrayList<Fruit> fruits = new ArrayList<Fruit>();
interface FruitVisitor {
void visit(Banana banana);
void visit(Apple apple);
}
如果水果是香蕉,我想看看它有多圆,所以
for (Fruit f : fruits) {
if (f instanceof Bannana)
f.checkHowRoundBannanaIs();
}
我必须将checkhowrandbannnais()
方法放在水果类中,即使水果可能不是香蕉,因为如果f不在水果类中,我就不能在f上使用该函数,否则会出现未定义的方法错误(或类似错误)
对于一个或两个方法来说,这很好,但过了一段时间,它会使类变得笨重和丑陋。因此,我的问题是,如何向类添加方法并在其超类的for样式循环中使用它们?最类似于您尝试将
f
转换为香蕉的技术:
if(f instanceof Bannana)
((Banana)f).checkHowRoundBannanaIs()
我不确定这是否真的是你想要的
所以我的问题是,如何向类添加方法并在其超类的for样式循环中使用它们?
简单的回答,你真的不能
如果要调用for循环体中的方法,instanceof
和向下转换是我能想到的唯一方法:
for (Fruit f : fruits) {
if (f instanceof Banana)
((Banana) f).checkHowRoundBananaIs();
// ...
}
不过,实例和向下投射通常都被认为是不好的做法。为了避免这种情况,您可以实现。以下是您需要采取的步骤:
创建一个如下所示的访问者界面:
ArrayList<Fruit> fruits = new ArrayList<Fruit>();
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);
您不必将checkHowRoundBanannaIs()
放入Fruit
类中。一旦您知道f
是Banana
的一个实例,您就可以安全地将f
强制转换为类型Banana
。现在您有了一个Banana
实例,可以调用任何Banana
特定方法(包括checkhowrandbananais()
)
既然你已经在检查它是否是香蕉,你可以把它扔给香蕉,然后再做检查
for(fruit f : fruits)
{
if(f instanceof Banana) {
Banana b = (Banana)f;
b.checkHowRoundBananaIs()
}
}
…从逻辑上讲,这不是“它的超级类的for样式循环”
如果您要导入Bannana的实例,则必须导入Bannana的实例(虽然我想您应该改为键入Banana)。导入后,没有理由不将f
强制转换为Banana
。这样做可以访问Banana
的所有方法
简言之,除非您确实想将obj1
用作XXX
,否则通常不会执行XXX的obj1实例检查
当然还有更好的方式,比如访问者模式(参见其他帖子)或者将函数提取到超类。虽然我想你已经接受了设计上的一些问题,但你不想解决它。这些示例是用Java编写的,但这不是Java的问题。对。这个问题对于使用单一分派机制的所有语言来说都是常见的。
for(fruit f : fruits)
{
if(f instanceof Bannana)
f.checkHowRoundBannanaIs()
}