Java 如果程序设计正确,为什么会有人重写这些方法呢?

Java 如果程序设计正确,为什么会有人重写这些方法呢?,java,inheritance,interface,overriding,Java,Inheritance,Interface,Overriding,我了解覆盖的工作原理和作用。我不明白的是,如果类设计得“正确”,为什么会有人需要使用它 例如,假设我有一个名为Animal的类,并且我添加了一个speak方法。然后,我有一些从动物身上继承下来的类,比如牛、狗和猫。但每一种“说话”方式都不同。奶牛做:system.out.println(“moo”)。狗“汪汪”叫,猫“喵喵”叫 我的问题是,如果牛、狗和猫都必须重写speak方法,那么为什么我要把speak放在动物类的首位呢 我试着在网上和Stackoverflow上寻找原因,但似乎没有人给我一个

我了解覆盖的工作原理和作用。我不明白的是,如果类设计得“正确”,为什么会有人需要使用它

例如,假设我有一个名为Animal的类,并且我添加了一个speak方法。然后,我有一些从动物身上继承下来的类,比如牛、狗和猫。但每一种“说话”方式都不同。奶牛做:system.out.println(“moo”)。狗“汪汪”叫,猫“喵喵”叫

我的问题是,如果牛、狗和猫都必须重写speak方法,那么为什么我要把speak放在动物类的首位呢


我试着在网上和Stackoverflow上寻找原因,但似乎没有人给我一个具体的答案。我所能做的最好的事情是,我真的应该使用一个接口来代替(从那些声称从具体类扩展是邪恶的帖子中)

这样,当你有一个动物实例时,你就可以确保它会说话()。这就是合同设计的原则。动物类(合同)向您保证,任何兄弟姐妹都会说话。事实上,任何兄弟姐妹都有自己的方式,这就是多态性


对于你的附带问题,我理解为什么会在接口上使用抽象方法——当你有某种标准方法或默认方法在父类中实现该方法时,这很有用,即使你没有能力在父类中完全实现它,此外,抽象方法与常规方法的不同之处在于,它将强制子类按照接口的方式实现该方法。

通常,抽象类(如Animal类)旨在为Animal的所有子类提供特定的接口。Animal的抽象部分允许程序员意识到他必须为
说话
创建一个方法。毕竟,每种动物说话的方式都不同,而且动物说话没有“默认”方式。

如果动物没有speak()方法,那么如果你这样做了

Animal a = new Dog();
你做不到

a.speak();

即使Dog有一个
speak()
方法,这也是面向对象编程的本质,在您所举的示例中。动物是一个原型(理想情况下,这应该是您的界面),它定义了动物的特征。这意味着任何你称之为动物的东西都应该有这些特征。这就是你将所有动物都绑定为动物类型的方式。当你从设计的角度来看它时,你会得到一个清晰的画面

一个答案是多态性

当在
Animal
级别定义speak时,它允许我这样做

ArrayList<Animal> animals = new ArrayList<Animal>();
animals.add(new Dog("Charlie"));
animals.add(new Bird("Tweety"));
animals.add(new Duck("Cheese and Quackers"));

for( Animal a : animals ) 
    a.speak();
ArrayList animals=new ArrayList();
动物。添加(新狗(“查理”);
动物。添加(新鸟(“Tweety”);
动物。添加(新鸭子(“奶酪和嘎嘎”);
(动物a:动物)
a、 说();
由于speak在基类中定义了一个基本行为,我可以保证会有一些speak行为,因此我可以从基类调用该行为安全性,而不会有调用类上不存在的方法的风险。如果特定的类有一个更复杂的实现,这很好,但我至少保证有一些实现。如果长颈鹿没有实现speak,我不想担心——通过扩展已经定义了最低例程的animal,根据合同,我可以保证有一些实现我可以使用

您也可以通过接口来实现这一点,但在某些情况下,接口不如扩展方便,因为接口要求所有实现类都有自己的实现,这在许多情况下是一种时间浪费

这就引出了我的第二个答案:简单


你说(意译)‘如果所有对象都必须实现speak,并且所有对象都以不同的方式说话’。这是一个很大的假设。如果90%的动物说的是相同的,而只有一些动物说的是不同的呢。考虑<代码>猴子>代码>代码>人类<代码> >代码> CAT<代码>和<代码>心灵感应猫< /代码>。在这里,我可能会争辩说,前三种说法是相同的。唯一需要自己说话的人是心灵感应猫,因为它使用不同的说话方法。在这种情况下,只定义两次speak很有用。在
动物
中使用一次,在特殊情况下使用
心灵感应猫
进行第二次。这使得代码维护更加简单。如果每个人的语言都是不同的,那么也许界面就是你想要的,但是如果大多数动物的语言都是相同的,那么继承就占了上风

假设我有一个包含牛、狗和猫的动物列表。我想让所有的动物都说话<(动物a:动物)a.说()您的示例很糟糕,但让我们继续。也许您创建了一个
动物
,而不是它的子类,而这个
动物
需要能够说话。此外,可能不是所有的子类都重写该方法
Cat
Cow
覆盖它,但
Dog
对其父类的实现感到满意。如果不将speak方法放在Animal类中,则动物将无法说话。但这是动物的契约,它会说话,所以方法必须在课堂上。你们是最好的!非常感谢。现在100%理解:)一个非常重要的词:多态性。你可以有一个
动物
的列表,所有这些动物都可以使用这种说话行为来进行行为,因为猫说话不像狗,所以它们必须独立执行该行为。你不必把所有这些
Animal
s投给他们各自的班级,以获得你关心的输出,以及他们发言时所说的话。我真的很感兴趣,谁否决了所有这些答案,欢迎解释。嗯,我问了最初的问题,我认为这是一个很好的和有益的解释。非常感谢,非常感谢