【问题标题】:java - inherited class issue (different methods in subclasses than super) [duplicate]java - 继承类问题(子类中的方法与超类不同)[重复]
【发布时间】:2014-08-29 18:24:40
【问题描述】:

我有一个超类动物和一堆继承类...狗、猫和猪等。

我的问题是所有的狗猫和猪都有自己不同的参数。类“动物”是一个引入参数对象。

所以,狗可能有 getbark.. pig 可能有 getoink..

我有一个方法将“pig”与类 pig.. 联系起来,还有一个 getter,当我 get("pig"); 时返回动物类型。和其他人一样..

问题是,如果我做 Animal Animal = get("pig"),然后尝试对动物使用 pig 的方法.. 即。动物.oink(), 我得到“动物类型的方法是 undef”,因为 oink 不在动物中,它在猪中。

我能想到解决这个问题的唯一方法是将 oink、woof、meow、neigh 和其他 20 种方法放在超类中。这很愚蠢,因为 dog 只需要 woof,而不需要 oink、meow、neigh,唧唧喳喳……

我很抱歉这个令人费解的例子。这是我能想到的唯一解释方法。我知道你不能在 Java 中沮丧。,有什么解决方案吗?

编辑:

这只是一个简单的例子.. 不仅仅是一个说话功能。例如,狗具有猪没有的“梳子”功能。 我可以在超类中有一个通用的 dothings() 方法,并在子类中有一堆方法多次覆盖相同的 dothings 方法吗?

【问题讨论】:

  • 这叫做铸造...Pig pig = (Pig) get("pig"); pig.oink();。还可以考虑在Animal 中使用public abstract void makeSound();
  • 为什么不在子类中覆盖 getSound() 方法?

标签: java inheritance


【解决方案1】:

您的问题源于您决定为这些方法中的每一个赋予不同的名称。乍一看,它们似乎都在做不同的事情,因为所有动物都会发出不同的声音,但最好只有一种方法,比如 makeSound,在 Animal 中声明,然后在你的子类。这样,您就可以从Animal 调用该方法。这是一个极简主义的例子:

class Animal
{
    public abstract void makeSound();
}

class Pig extends Animal
{
    public void makeSound()
    {
        System.out.println("oink!")
    }
}

class Dog extends Animal
{
    public void makeSound()
    {
        System.out.println("Woof!")
    }
}

允许这样使用:

Animal dog = get("Dog");
dog.makeSound(); //prints "Woof!"

这是有道理的,因为不管它们发出什么声音,每只动物确实可以发出声音,因此应该在类 Animal 中声明行为,并且可以为每只动物指定发出什么声音,而无需添加任何东西到类的公共方法。

【讨论】:

  • 不用makeSound(),用vocalize()怎么样?否则,不清楚应该从动物的哪一端发出声音。
【解决方案2】:

如果先用instanceof测试对象的类型,可以向下转换。

但是,在这里使用多态性会更好。在Animal 中定义一个抽象的speak 方法,并让你的所有子类实现它,例如在Dog:

public void speak() { System.out.println("woof"); }

那么你在所有类中都有同名的方法,无论animal的实际类型如何,这都会起作用:

Animal animal = get("pig");  // or any other subtype
animal.speak();  // oink

【讨论】:

    【解决方案3】:

    有两种解决方案:

    1. 您必须将 Animal 转换为正确的子类,这种解决方案非常肮脏,并且不使用 OO 编程的强大功能。例如:

      if (animal instanceof Pig) {
          ((Pig)animal).oink();
      }
      
    2. 您必须为动物类使用通用方法,例如 doVerse(),并且您必须在每个子类中重写此方法。

      class Pig extends Animal {
      
          public void doVerse() {
             System.out.println("oink");
          }
      }
      

    【讨论】:

      【解决方案4】:

      此外,如果您想保留 speak 方法的特定名称(bark、meow、oink 等),请确保您是在该特定动物的实例上调用它们。

      超类的主要功能是为子类提供对它们通用的所有方法,而不必为每个子类编写方法。

      我绝对建议采用其他答案的多态性想法,但是当您继续前进时,它有助于具体了解超类的用途,以及子类如何拥有独特的方法。

      【讨论】:

      • 当您想要实现所有子类共享的公共行为时,请使用超类。如果你只想声明每个Animal必须能够vocalize(),那么Animal最好是interface
      猜你喜欢
      • 1970-01-01
      • 2015-03-14
      • 2021-05-04
      • 2013-10-23
      • 2018-07-25
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 2020-12-06
      相关资源
      最近更新 更多