你好!您已经使用过 Java 方法并且对它们了解很多。
您肯定遇到过一个类,该类包含许多名称相同但参数列表不同的方法。您会记得在那些情况下我们使用了方法重载。今天我们来看看不同的情况。想象一下,我们有一个通用方法,但它应该根据在哪个类中调用它来做不同的事情。我们如何实现这种行为?为了理解这一点,让我们以
我们想避免创造一堆说话的方法。我们不希望创建用于喵

Animal
代表动物的父类为例,并
speak
在其中创建一个方法:
public class Animal {
public void speak() {
System.out.println("Hello!");
}
}
虽然我们刚刚开始编写我们的程序,但您可能会看到一个潜在的问题:世界上有很多动物,它们“说话”的方式各不相同:猫叫、鸭叫、蛇嘶等等。我们的目标很简单:

meow()
喵叫、
hiss()
嘶嘶声等的方法,而是希望在调用该方法时蛇发出嘶嘶声、猫喵喵叫、狗吠叫
speak()
。
我们可以使用方法覆盖轻松实现这一点。维基百科对这个术语的解释如下:
Method overriding,在面向对象编程中,是一种语言功能,它允许子类或子类提供其超类或父类之一已经提供的方法的特定实现。这基本上是正确的。重写允许您采用父类的某些方法并在每个派生类中编写您自己的实现。子类中的新实现“替换”了父类中的实现。让我们通过一个例子看看这是什么样子的。让我们创建我们
Animal
班级的 4 个后代:
public class Bear extends Animal {
@Override
public void speak() {
System.out.println("Growl!");
}
}
public class Cat extends Animal {
@Override
public void speak() {
System.out.println("Meow!");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println("Woof!");
}
}
public class Snake extends Animal {
@Override
public void speak() {
System.out.println("Hiss!");
}
}
这是未来的一个小技巧:要覆盖父类的方法,请进入IntelliJ IDE 中派生类的代码,按Ctrl
+O,然后从菜单中选择
覆盖方法...。从一开始就习惯使用热键。他们将加快编码速度!为了获得所需的行为,我们做了一些事情:
- 在每个后代类中,我们创建了一个与父类中的方法同名的方法。
-
我们告诉编译器我们不只是给方法一个与父类中相同的名称,而是我们想要覆盖它的行为。这个给编译器的“消息”是通过@Override注释传达的。
方法上方的 @Override 注释告诉编译器(以及其他阅读您的代码的程序员),“别担心。这不是错误或疏忽。我知道这个方法已经存在,我想覆盖它. - 我们为每个后代类编写了我们需要的实现。调用该方法时
speak()
,蛇应该发出嘶嘶声,熊应该咆哮,等等。
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.speak();
animal2.speak();
animal3.speak();
animal4.speak();
}
}
控制台输出
Woof!
Meow!
Growl!
Hiss!
太好了,一切正常!我们创建了 4 个类型为父
Animal
类的引用变量,并为它们分配了 4 个不同的子类对象。因此,每个对象的行为都不同。对于每个派生类,覆盖的方法替换类的
speak()
现有方法(它只在控制台上显示“Speaking:”)。方法覆盖有几个限制:
speak()
Animal

-
重写的方法必须与父类中的方法具有相同的参数。
如果
speak
父类的方法以aString
为输入,那么子类中重写的方法也必须以aString
为输入。否则,编译器会产生一个错误:public class Animal { public void speak(String s) { System.out.println("Speaking: " + s); } } public class Cat extends Animal { @Override // Error! public void speak() { System.out.println("Meow!"); } }
-
重写的方法必须与父类中的方法具有相同的返回类型。
否则,我们会得到一个编译错误:
public class Animal { public void speak() { System.out.println("Hello!"); } } public class Cat extends Animal { @Override public String speak() { // Error! System.out.println("Meow!"); return "Meow!"; } }
-
重写方法的访问修饰符也不能与原始方法不同:
public class Animal { public void speak() { System.out.println("Hello!"); } } public class Cat extends Animal { @Override private void speak() { // Error! System.out.println("Meow!"); } }
speak()
每个人都有一个方法,而不是一堆不同的方法,例如
bark()
,
meow()
等等。
GO TO FULL VERSION