如何向类添加方法并在其超类的 for 样式循环中使用它们?

发布于 2024-12-09 06:36:37 字数 558 浏览 0 评论 0原文

假设我有一个像这样的通用数组:

ArrayList<Fruit>  fruits = new ArrayList<Fruit>();

然后我添加很多不同的水果,它们都扩展了水果类,并循环它们

for (Fruit f : fruits) {

}

如果水果是香蕉,我想检查它有多圆,所以..

for (Fruit f : fruits) {
    if (f instanceof Bannana)
        f.checkHowRoundBannanaIs();
}

我将有将 checkHowRoundBannaIs() 方法放在水果类中,即使水果可能不是香蕉,因为如果 f 不在水果类中,我就无法在 f 上使用该函数,否则我收到未定义的方法错误(或类似的错误) 那)。

这对于一两个方法来说是没问题的,但过了一段时间,它就会使类变得笨重且丑陋。所以我的问题是,如何向类添加方法并在其超类的 for 样式循环中使用它们?

Say I have a generic array like this:

ArrayList<Fruit>  fruits = new ArrayList<Fruit>();

Then I add lots of different fruits, which all extends the class fruit, and loop through them

for (Fruit f : fruits) {

}

If the fruit is a banana, I want to check how round it is, so..

for (Fruit f : fruits) {
    if (f instanceof Bannana)
        f.checkHowRoundBannanaIs();
}

I will have to put the checkHowRoundBannnaIs() method in the fruit class, even though the fruit may not be a banana, because I can't use the function on f if it isn't in the fruit class, otherwise I get a undefined method error (or something like that).

This is fine for one or two methods, but after a while it makes the class bulky and ugly. So my question is, how can I add methods to a class and use them in a for-style loop of its super class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

粉红×色少女 2024-12-16 06:36:37

所以我的问题是,如何向类添加方法并在其超类的 for 样式循环中使用它们?

简短的回答,你真的不能。

如果你想调用for循环体中的方法,instanceof和向下转换是我能想到的唯一方法:

for (Fruit f : fruits) {
    if (f instanceof Banana)
        ((Banana) f).checkHowRoundBananaIs();
    // ...
}

instanceof和向下转换但通常被认为是不好的做法。为了避免这种情况,您可以实施访问者模式。以下是您需要执行的步骤:

  1. 创建如下访问者界面:

    接口 FruitVisitor {
        无效访问(香蕉香蕉);
        无效访问(苹果苹果);
    }
    
  2. 让所有水果接受访问者:

    抽象类 Fruit {
        // ...
        公共抽象无效接受(FruitVisitor fv);
    }
    
    类香蕉延伸水果{
        公共无效接受(FruitVisitor fv){
            fv.访问(此);
        }
    
        公共无效 checkHowRoundBananaIs() { ... }
    }
    
  3. 创建一个对每种水果采取适当操作的访问者,并将其作为参数传递给accept 列表中每种水果的方法:

    FruitVisitor fv = new FruitVisitor() {
        公共无效访问(香蕉香蕉){
            香蕉.checkHowRoundBananaIs();
        }
    
        公共无效访问(苹果苹果){
            // ...
        }
    };
    
    对于(水果 f :水果)
        f.接受(fv);
    

So my question is, how can I add methods to a class and use them in a for-style loop of its super class?

Short answer, you can't really.

If you want to call the methods in the body of the for-loop, instanceof and down-casting is the only way I can think of:

for (Fruit f : fruits) {
    if (f instanceof Banana)
        ((Banana) f).checkHowRoundBananaIs();
    // ...
}

Both instanceof and down-casting are usually considered bad practice though. To avoid it, you could implement the visitor pattern. Here are the steps you would need to take:

  1. Create a visitor interface like this:

    interface FruitVisitor {
        void visit(Banana banana);
        void visit(Apple apple);
    }
    
  2. Let all fruits accept a visitor:

    abstract class Fruit {
        // ...
        public abstract void accept(FruitVisitor fv);
    }
    
    class Banana extends Fruit {
        public void accept(FruitVisitor fv) {
            fv.visit(this);
        }
    
        public void checkHowRoundBananaIs() { ... }
    }
    
  3. Create a visitor that takes the appropriate action for each type of fruit, and pass it as argument to the accept method of each fruit in your list:

    FruitVisitor fv = new FruitVisitor() {
        public void visit(Banana banana) {
            banana.checkHowRoundBananaIs();
        }
    
        public void visit(Apple apple) {
            // ...
        }
    };
    
    for (Fruit f : fruits)
        f.accept(fv);
    
各自安好 2024-12-16 06:36:37

与您尝试的最相似的技术是将 f 转换为 Banana

if(f instanceof Bannana)
    ((Banana)f).checkHowRoundBannanaIs()

但我不确定这是否真的是您想要的。

The technique most similar to what you tried there would be to cast f as a Banana:

if(f instanceof Bannana)
    ((Banana)f).checkHowRoundBannanaIs()

I'm not sure whether this is really what you want or not though.

只是我以为 2024-12-16 06:36:37

您不必将 checkHowRoundBanannaIs() 放入 Fruit 类中。一旦您知道 fBanana 的实例,您就可以安全地将 f 向下转换为 Banana 类型。现在您已经有了一个 Banana 实例,您可以调用任何 Banana 特定方法(包括 checkHowRoundBananaIs())。

for(final Fruit f : fruits)
{
    if(f instanceof Banana)
    {
        final Banana b = (Banana) f;
        b.checkHowRoundBananaIs();
    }
}

You don't have to put checkHowRoundBanannaIs() in the Fruit class. Once you know that f is an instance of Banana you can safely down-cast f to the type Banana. Now that you have a Banana instance, you can call any Banana specific method (including checkHowRoundBananaIs().

for(final Fruit f : fruits)
{
    if(f instanceof Banana)
    {
        final Banana b = (Banana) f;
        b.checkHowRoundBananaIs();
    }
}
天涯离梦残月幽梦 2024-12-16 06:36:37

既然您已经在检查它是否是香蕉,您可以将其投射到香蕉上然后进行检查。

for(fruit f : fruits)
{
    if(f instanceof Banana) {
        Banana b = (Banana)f;
        b.checkHowRoundBananaIs()
    }
}

Seeing as you are already checking if it's a banana, you could cast it to a banana then do the check..

for(fruit f : fruits)
{
    if(f instanceof Banana) {
        Banana b = (Banana)f;
        b.checkHowRoundBananaIs()
    }
}
反差帅 2024-12-16 06:36:37
for(fruit f : fruits)
{
  if(f instanceof Bannana)
      f.checkHowRoundBannanaIs()
}

...这不是“其超类的 for 样式循环”。从逻辑上来说。

ASA,您执行 instanceof Bannana 时,必须导入 Bannana (尽管我想您想输入 Banana)。导入后,没有理由不将 f 转换为 Banana。只要您这样做,您就可以访问 Banana 的所有方法。

简而言之,通常您不会执行 obj1 instanceof XXX 检查,除非您确实想将 obj1 用作 XXX

当然,还有更好的方法,例如访问者模式(请参阅其他帖子)或将函数提取到超类。尽管我猜你已经接受了设计上存在一些问题并且你不想修复它。

for(fruit f : fruits)
{
  if(f instanceof Bannana)
      f.checkHowRoundBannanaIs()
}

... that is NOT a "for-style loop of its super class". Logically speaking.

ASA you do instanceof Bannana you have to import Bannana (though I suppose you wanted to type Banana instead). Once imported, there is no reason not to cast f to Banana. One you do that you have access to all methods of Banana.

In short, usually you don't do obj1 instanceof XXX check unless you actually want to use obj1 as XXX.

Of course there are better ways like the visitor pattern (see other posts) or extracting the function to super class. Though I guess you have accepted that you have some problem with design and you don't wanna fix it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文