【问题标题】:Subclasses as arguments to abstract method子类作为抽象方法的参数
【发布时间】:2014-11-04 19:04:58
【问题描述】:

在我的程序中,我有抽象类 Animal 和 Flower。动物吃花,但每个动物只能吃某种类型的花(例如,犀牛只吃玫瑰,乌龟吃郁金香)。

现在我的代码基本上是这样的:

public abstract class Animal {
    abstract boolean eatFlower(Flower f);
}

public class Rhino extends Animal {
    boolean eatFlower(Flower f) {
        if(!(f instanceof Rose)) return false;
        return (f.eaten = true);
    }
}

public class Turtle extends Animal {
    boolean eatFlower(Flower f) {
        if(!(f instanceof Tulip)) return false;
        return (f.eaten = true);
    }
}

我使用instanceof 来加强这种区别,即每只动物只吃一种花。我想通过将 Turtle 和 Rhino 的方法签名分别更改为 eatFlower(Tulip t)eatFlower(Rose r) 来做到这一点,但我认为这在 Java 中是不可能的。

有没有比使用instanceof 更好的方法来强制执行此操作?

【问题讨论】:

    标签: java oop polymorphism instanceof


    【解决方案1】:

    您可以使用泛型。像这样的:

    public abstract class Animal<T extends Flower> {
        abstract void eatFlower(T f);
    }
    
    public class Rhino extends Animal<Rose> {
        void eatFlower(Rose f) {
    
        }
    }
    

    【讨论】:

      【解决方案2】:

      是的,有更好的方法。您可能不想在参数中强制执行该类型。

      原因是,运行时和编译时多态性之间存在重大差异。现在,当你编译代码时,你必须知道(所有)动物可以吃的花的类型。这可以防止您在没有代码更新的情况下更改该数据,并且会丢失相当多的抽象。

      Animal 的合同是它吃某种类型的Flower,但你不知道那是什么。事实上,只有那只特定的动物确切地知道它喜欢什么类型的花。也许你有一个对BlueRoses 不宽容的Rhino,他只能吃RedRoses。

      除非您毫无疑问地知道所有Rhinos 都会吃掉所有Roses 并且愿意永远致力于这种情况(或直到您的下一个主要版本),否则您不应该让它成为一部分接口的公共合约。在不久的将来的某个时候,Rhinos 可能会意识到Daisies 一样好吃,一个可以同时吃的亚种诞生了。一旦某事公开,您只能减少限制。

      Rhino 遇到Flower 时,它必须选择是否有能力吃掉那朵特定的花。犀牛每天早上醒来时不会列出所有好花,所以你可能不应该在代码中将它们全部硬编码。

      您有两种选择,具体取决于您希望如何执行该选择。您可以检查传递的Flower 是否为instanceof 已知良好类型,这要求您知道所有良好类型都是编译时的。您还可以将FlowerType getType() 方法添加到Flowers,调用它,并将结果与​​Set&lt;FlowerType&gt;goodFlowers` 进行比较。如果有必要,这允许您在运行时更改可接受的花朵。

      一般来说,多个instanceof 检查(如果犀牛可以吃另一种花,你会得到)通常可以指示设计缺陷。它们可能会通过紧密绑定两个原本不相关的类型而损害抽象,并且可能会被数据(来自枚举、数据库、文件或其他来源)替换。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-04
        • 1970-01-01
        • 1970-01-01
        • 2019-06-26
        • 2023-03-29
        • 1970-01-01
        • 2022-08-18
        • 1970-01-01
        相关资源
        最近更新 更多