Java 中的方法重写
在子类上重写父类方法,让调用走子类的方法体。保持 Truck extends Car。在 Car 上保留打印 beep 的 horn。在 Truck 上再写一遍 horn,让它打印 honk。在 Yard.java 里创建一个 Truck 并调用 t.horn()。用 javac Yard.java 编译,再运行 java Yard。屏幕应显示 honk。第二个演示还会创建一个普通 Car,让你听到父类的 beep 和子类的 honk。接口留给下一页——本课是同一个方法名、两套方法体。
在子类上重写 horn
继承页让 Truck 保持为空,于是 t.horn() 仍用父类的 beep。super 页用 super 跑构造器。本页改的是子类上的方法体。打开 Yard.java。保持 public 类名为 Yard。若只打印构造器里的 car 和 truck 会盖住方法故事,就删掉它们,并删掉残留路径演示、Store 写入器,以及任何键盘 Scanner。程序不应等待输入。不需要 import 行。
声明带实例方法的父类,让它打印 beep:
class Car {
void horn() {
System.out.println("beep");
}
}
用 extends Car 声明子类。在 Truck 里再写同名方法,但打印 honk:
void horn() {
System.out.println("honk");
}
名称相同、空参数列表也相同,表示对 Truck 对象来说,子类版本会替换父类版本。你不是在加第二个无关方法。你是在重写 horn。
在 Yard.main 里创建一个 truck 并调用方法:
Truck t = new Truck();
t.horn();
这次调用运行写在 Truck 上的方法体,所以屏幕打印 honk。
class Car {
void horn() {
System.out.println("beep");
}
}
class Truck extends Car {
void horn() {
System.out.println("honk");
}
}
public class Yard {
public static void main(String[] args) {
Truck t = new Truck();
t.horn();
}
}
在存放 Yard.java 的文件夹里运行 javac Yard.java。当圆括号、花括号和分号都匹配时,javac 自己不写输出行。然后运行 java Yard——不要写成 java Yard.java。运行命令里去掉 .java 后缀。文件里只保留一个 public 类,使名称与 Yard 一致。辅助类型 Car 和 Truck 在本入门形态下不加 public。
屏幕显示 honk。把这次运行走一遍。Java 从 Yard.main 开始。new Truck() 创建一个 truck。t.horn() 查看 t 的真实类型。因为 Truck 写了自己的 horn,子类方法体运行并打印 honk。父类的 beep 方法体仍留在 Car 上,不会用于这次 truck 调用。
若仍看到 beep,检查 Truck 是否真的含有 horn 方法。继承页留下的空 Truck 仍会继承 beep。重写要求子类方法以相同名称存在。若仍看到构造器演示里的 car 然后 truck,切换到 override 教学文件,再运行一次 java Yard。
看着屏幕把规则说出来:子类上同名方法,对该对象而言子类方法体胜出。保持 extends Car,让 Truck 仍是一种 Car。没有 extends 时,Truck 上的 horn 会变成另一套类型故事,而不是对父类方法的重写。
此页不要发明 interface 文件。接口留给下一课。今天一个类层次带着两套 horn 方法体,子类方法体响应 truck 上的调用。
父类 beep 与子类 honk 并排
第二个程序保留重写。main 同时创建 Car 和 Truck,再分别调用 horn。父类仍打印 beep。子类仍打印 honk。
class Car {
void horn() {
System.out.println("beep");
}
}
class Truck extends Car {
void horn() {
System.out.println("honk");
}
}
public class Yard {
public static void main(String[] args) {
Car c = new Car();
Truck t = new Truck();
c.horn();
t.horn();
}
}
用 javac Yard.java 编译,再运行 java Yard。屏幕先显示 beep,再显示 honk。第一行来自 Car 对象。第二行来自 Truck 对象。在子类上重写不会抹掉父类对象上的父类方法。每个对象使用属于自己类型的方法体。
再读一遍两个 horn 方法。同名。同样的空参数列表。不同的打印文本。正是签名一致,才让子类版本成为重写,而不是新的无关方法。若把子类方法改成别的名字,继承会再次让 truck 保留 beep,你就不再在教 override。
若文件夹里还有带 super() 的构造器演示,当作历史留下。本课请运行 override 教学文件,让屏幕显示方法打印,而不是构造器顺序词。若 javac 抱怨重复的 public 类,说明文件里仍有不止一个 public 类——只让 Yard 保持 public。
父类方法体对照子类方法体
📊 Who prints what for horn
| Role | horn body |
|---|---|
Parent Car |
prints beep |
Child Truck |
prints honk (overrides) |
这张表是本页的短地图。若只有继承且子类为空,两个角色都会是 beep。重写之后,子类行变成 honk,父类行仍是 beep。第二个演示打印两行时,把这张地图记在心里。 |
对照空的 extends 与对照 super
在继承页,空的 Truck 保留父类 horn 并打印 beep。在 super 页,构造器经 super 运行并先打印 car 再打印 truck。本页改的是子类上的方法本身。你仍需要 extends。以后仍可用构造器。现在还不需要接口。
若仍打开着残留的空 Truck,先加上打印 honk 的子类 horn,再判断屏幕。若仍打开着构造器文件,切换到 override 文件,让受测调用是 t.horn()。新记号是子类上重写的方法,以及屏幕上两个不同的词 beep 与 honk。
进入接口之前
你可以在 Truck 上重写 horn,并从 t.horn() 看到 honk。你可以同时调用 c.horn() 和 t.horn(),看到先 beep 再 honk。对每个保留的演示,依次编译 Yard.java 并运行 java Yard。子类方法体回答了 truck 调用。下一页是接口:类型可以承诺方法,而不只靠 extends。
保留单 truck 的 honk 演示,把重写看清楚。保留双对象演示,把父类与子类对比看清楚。此页不要放接口文件。这三条习惯是继续前进前的检查点。当 t.horn() 之后出现 honk,且 c.horn() 之后仍出现 beep 时,重写完成本课任务,你就可以进入下一主题——接口。
最后再扫一遍文件夹:一个 public Yard、两个辅助类型、一个打印 honk 的子类 horn、没有键盘等待、没有强塞接口。对仍打开的演示再跑一次 javac Yard.java 和 java Yard。若屏幕仍与表格一致——父类 beep、子类 honk——重写就站得住,课程可以在下一页进入接口。
🧠 测试您的知识
测试您的知识
通过这个互动测验挑战自己,看看你对这个主题的理解程度如何
📝 说明
- 仔细阅读每个问题
- 为每个问题选择最佳答案
- 您可以随时重新参加测验
- 您的进度将显示在顶部