正在加载...

Java 中的抽象类

当父类必须至少留一个无方法体给子类填满时,把父类标成 abstract。写出带 abstract void horn(); 与普通方法 park(打印 park)的 abstract class Machine。写出 class Truck extends Machine,给 horn 一个打印 honk 的方法体。在 Yard.java 中创建一个 Truck,调用 t.horn(),再调用 t.park()。用 javac Yard.java 编译,再运行 java Yard。屏幕应先显示 honk,再显示 park。第二个演示加入 Car,让两个子类以不同方式填满 horn。把 polymorphism 留给下一页——本课是未完成的父类方法,以及把它写完的子类。

在子类上填满 abstract 方法

枚举页列出了固定名称。本页故意留下一个未完成的方法。打开 Yard.java。保持公共类名为 Yard。若残留的 enum Level 演示会淹没 abstract 主线,请删除它们,以及 Signal / implements 文件、路径演示和任何键盘 Scanner。程序不得等待输入。不需要 import 行。
在其它类型上方声明 abstract 父类:
abstract class Machine {
abstract void horn();
void park() {
System.out.println("park");
}
}
abstract 方法以分号结束,没有 { } 方法体。普通方法 park 保留完整方法体,好让每个子类复用。
用 extends Machine 声明子类。填满 horn:
void horn() {
System.out.println("honk");
}
你必须填满父类上列出的每一个 abstract 方法。本页只有 horn。不要在 main 里写 new Machine()——abstract 类不能单独建成对象。
在 Yard.main 内:
Truck t = new Truck();
t.horn();
t.park();
第一次调用运行 Truck 上的方法体。第二次调用运行 Machine 上的共享方法体。

Yard Truck fills abstract horn then park

java
abstract class Machine {
    abstract void horn();
    void park() {
        System.out.println("park");
    }
}

class Truck extends Machine {
    void horn() {
        System.out.println("honk");
    }
}

public class Yard {
    public static void main(String[] args) {
        Truck t = new Truck();
        t.horn();
        t.park();
    }
}

从存放 Yard.java 的文件夹运行 javac Yard.java。当圆括号、花括号和分号都匹配时,javac 不写自己的输出行。然后运行 java Yard——不要写成 java Yard.java。运行命令不要带 .java 后缀。文件里只保留一个公共类,使名称与 Yard 一致。辅助类型 Machine 与 Truck 在本入门形态中不加 public。
屏幕先显示 honk,再显示 park。把运行走一遍。Java 从 Yard.main 开始。new Truck() 创建一个已完成 abstract horn 的 truck。t.horn() 打印 honk。t.park() 从原本已有的父类方法体打印 park。未完成的方法只作为要求存在,直到子类写出方法体。
若 javac 拒绝,检查三件事。第一,父类那一行必须写 abstract class Machine。第二,未完成方法必须写 abstract 并以 ; 结束。第三,Truck 必须真正写出带方法体的 horn。若仍看到来自枚举文件的 MEDIUM,切到 abstract 教学文件再运行 java Yard。若尝试 new Machine(),javac 会拒绝——本页预期如此。
看着屏幕大声说出规则:abstract 父类命名缺失的方法,子类填满它,共享方法仍会运行。先不要发明一长串父类型变量的 polymorphism 游行。那个故事留给下一课。

两个子类以不同方式填满 horn

第二个程序保留同一个 abstract Machine。Truck 仍打印 honk。新的 Car 打印 beep。main 创建两者,各自调用 horn,再在 truck 上调用 park。

Yard Truck and Car fill horn then park

java
abstract class Machine {
    abstract void horn();
    void park() {
        System.out.println("park");
    }
}

class Truck extends Machine {
    void horn() {
        System.out.println("honk");
    }
}

class Car extends Machine {
    void horn() {
        System.out.println("beep");
    }
}

public class Yard {
    public static void main(String[] args) {
        Truck t = new Truck();
        Car c = new Car();
        t.horn();
        c.horn();
        t.park();
    }
}

用 javac Yard.java 编译,再运行 java Yard。屏幕先显示 honk,再显示 beep,再显示 park。每个子类用自己的打印填满了同一个 abstract 名称。共享的 park 方法体仍来自 Machine。你仍然从不写 new Machine()。
再读一遍父类:一个 abstract 方法,一个普通方法。再读子类:各自写出 horn,本页谁也不重写 park。这个分工就是教学要点。若在 Car extends Machine 时省略 Car 上的 horn,javac 会拒绝,因为每个 abstract 方法都必须填满。
若附近还有残留枚举演示,把它们当历史留下。本课请运行 abstract 教学文件,让屏幕显示方法填满,而不是 MEDIUM。若 javac 抱怨重复的公共类,只让 Yard 保持 public。

与枚举和接口对照

在枚举页,Level 列出固定名称。在接口页,implements 填满空的接口方法。在本页,abstract class 加上 extends 会留下一个未完成的类方法,直到子类写出方法体。你仍编译 Yard.java 并运行 java Yard。新记号是 abstract class、abstract void horn();,以及在复用 park 的同时提供方法体的子类。
若仍打开残留的 enum Level 文件,你会看到常量,也许还有 switch。切到 abstract 文件,让顶部显示 abstract class Machine,且 main 创建一个 Truck。把只挪动父类型变量的 polymorphism 演示留在本页之外。把键盘输入留在本页之外。

这给 polymorphism 留下什么

本页在具体子类上完成 abstract 方法。下一页展示 polymorphism:一个父类型变量可以持有不同子类对象,并调用匹配的方法体。这里先留在 abstract 父类与已填满的子类。先不要强制一份指向许多子类的 Machine 变量列表。
你以后写 polymorphism 演示时,往往仍会从 abstract 或普通父类方法名起步。把本页当作那个相邻故事的「未完成方法」半边。把两个 Yard 演示练到 honk 再 park——以及 honk、beep、park——都像自动反应,再打开 polymorphism 课。

进入 polymorphism 之前

你可以声明 abstract class Machine,在 Truck 上填满 horn,看到 honk 再 park。你可以加入带自己 horn 的 Car,看到 honk,再 beep,再 park。对每个保留的演示依次编译 Yard.java 并运行 java Yard。子类完成了 abstract 方法。下一页是 polymorphism:经由父类型引用的调用会选中子类方法体。
保留单 truck 演示,看清 abstract 填满加共享 park。保留双子类演示,看清一对填满。把 polymorphism 游行文件留在本页之外。这三条习惯是继续前进前的检查点。当 new Truck() 之后 honk 出现在 park 之前,abstract 类已完成本课工作,你已准备好进入关于 polymorphism 的下一主题。
最后再扫一遍文件夹:一个公共 Yard、一个 abstract Machine、填满 horn 的具体子类、没有 new Machine()、没有键盘等待。对你打开的演示再跑一次 javac Yard.java 和 java Yard。若屏幕仍打印你写的填满结果,abstract 约定就稳了,课程可以在下一页进入 polymorphism。

🧠 测试您的知识

准备开始

测试您的知识

通过这个互动测验挑战自己,看看你对这个主题的理解程度如何

❓
6
问题
🎯
70%
及格要求
♾️
∞
时间
🔄
∞
尝试次数

📝 说明

  • 仔细阅读每个问题
  • 为每个问题选择最佳答案
  • 您可以随时重新参加测验
  • 您的进度将显示在顶部