你好!您已经使用过 Java 中的方法并且对它们了解很多。您可能遇到过这样的情况:一个类中有许多具有相同名称但参数不同的方法。如果您还记得,在这些情况下我们使用了方法重载机制。今天我们来看一个不同的情况。想象一下,我们有一个通用方法,但它应该根据调用它的类来执行不同的操作。如何实施这种行为?为了弄清楚这一点,让我们采用一个
Animal
表示动物的父类并在其中创建一个方法voice
- “ voice ”:
public class Animal {
public void voice() {
System.out.println("Voice!");
}
}
尽管我们刚刚开始编写程序,但您很可能会看到潜在的问题:世界上有很多动物,它们的“说话”方式都不同:猫喵叫、鸭子嘎嘎叫、蛇嘶嘶声。 我们的目标很简单:避免创建一堆投票方法。我们不希望创建喵voiceCat()
喵声、voiceSnake()
嘶嘶声等方法,而是希望voice()
在调用方法时蛇发出嘶嘶声、猫发出喵叫声、狗发出吠叫声。我们可以使用方法重写机制(Java中的Override)轻松实现这一点。维基百科对术语“覆盖”给出了以下解释: 面向对象编程中的方法覆盖是编程语言的功能之一,它允许子类或子类提供已在超类之一中实现的方法的特定实现。或家长班。总的来说,这是正确的。重写允许您采用父类的方法并在每个后代类中编写您自己的该方法的实现。新的实现将“替换”子类中的父类。让我们通过一个例子来看看它是什么样子的。让我们为我们的类创建 4 个后继类: Animal
public class Bear extends Animal {
@Override
public void voice() {
System.out.println("Р-р-р!");
}
}
public class Cat extends Animal {
@Override
public void voice() {
System.out.println("Meow!");
}
}
public class Dog extends Animal {
@Override
public void voice() {
System.out.println("Woof!");
}
}
public class Snake extends Animal {
@Override
public void voice() {
System.out.println("Ш-ш-ш!");
}
}
未来的一个小窍门:要重写父类的方法,请转到Intellij IDE a 中的后代类的代码,按Ctrl+O并从菜单中选择“重写方法... ”。从一开始就习惯使用热键,它会加快编写程序的速度!为了设置我们想要的行为,我们做了一些事情:
- 我们在每个后代类中创建了一个与父类中的方法同名的方法。
-
我们告诉编译器我们将该方法命名为与父类中相同的方法是有原因的:我们想重写它的行为。为了向编译器传递这个“消息”,我们在方法上添加了@Override 注释。
放置在方法上方的 @Override 注释告诉编译器(以及也阅读您代码的程序员):“一切都很好,这不是一个错误或我的健忘。我记得这样的方法已经存在,我想重写它。” - 我们为每个后代类编写了所需的实现。当被召唤时,蛇
voice()
应该发出嘶嘶声,熊应该咆哮,等等。
public class Main {
public static void main(String[] args) {
Animal animal1 = new Dog();
Animal animal2 = new Cat();
Animal animal3 = new Bear();
Animal animal4 = new Snake();
animal1.voice();
animal2.voice();
animal3.voice();
animal4.voice();
}
}
控制台输出: 汪!喵!呃呃!嘘! 太好了,一切都按预期进行!我们创建了父类的 4 个引用变量Animal
,并将它们分配给后代类的 4 个不同对象。因此,每个对象的行为都不同。对于每个后代类,重写的方法替换了该类中的voice()
“本机”方法(它只是将“Voice!”输出到控制台)。 覆盖有许多限制: voice()
Animal
-
重写的方法必须具有与父方法相同的参数。
voice
如果父类中的方法接受作为输入String
,则子类中重写的方法也必须接受作为输入String
,否则编译器将抛出错误:public class Animal { public void voice(String s) { System.out.println("Voice! " + s); } } public class Cat extends Animal { @Override//error! public void voice() { System.out.println("Meow!"); } }
-
重写的方法必须具有与父方法相同的返回类型。
否则,我们会收到编译错误:
public class Animal { public void voice() { System.out.println("Voice!"); } } public class Cat extends Animal { @Override public String voice() { //error! System.out.println("Meow!"); return "Meow!"; } }
-
重写方法的访问修饰符也不能与“原始”方法不同:
public class Animal { public void voice() { System.out.println("Voice!"); } } public class Cat extends Animal { @Override private void voice() { //error! System.out.println("Meow!"); } }
voice()
而不是一堆方法等。 voiceDog()
voiceCat()
GO TO FULL VERSION