抽象类与抽象方法
本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 32 课,共 87 课。
有时,你想定义一个用作蓝图、但永远不应直接实例化的类。例如,通用的 Shape 类适合作为父类,但没有具体形状的“形状”会是什么样子?这时就需要用到抽象类。
抽象类使用 abstract 关键字声明,不能实例化。它可以包含有实现的普通方法,也可以包含没有方法体的抽象方法:
public abstract class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
// 抽象方法:没有具体实现
public abstract double getArea();
// 普通方法:有具体实现
public String getColor() {
return color;
}
}抽象方法声明子类必须做什么,但不声明如何做。任何继承抽象类的非抽象类都必须为所有抽象方法提供实现:
public class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}你仍然可以将抽象类用作引用类型,从而实现多态:
Shape shape = new Circle("red", 5.0);
System.out.println(shape.getArea()); // 调用 Circle 的实现当子类共享一些代码,但必须以不同方式实现某些行为时,抽象类就很适用。它们既能规定契约,又能复用代码。
挑战
简单让我们构建一个家电系统,展示抽象类的强大之处。你将创建一个基础 Appliance 类,定义每种家电都必须执行的操作,同时让具体的家电类型自行决定如何执行。
你将把代码分成四个文件:
Appliance.java:创建一个抽象类,作为所有家电的蓝图。每种家电都有一个brand字段(String)和一个wattage字段(int)。添加一个用于初始化这两个字段的构造函数、分别获取这两个字段的 getter 方法,以及一个返回[brand] - [wattage]W的普通方法getInfo()。定义一个抽象方法operate(),子类必须实现它,用来表示每种家电如何执行其主要功能。WashingMachine.java:创建一个继承自 Appliance 的具体类。洗衣机有一个额外的capacity字段(int),表示以 kg 为单位的装载量。使用super处理父类的初始化。实现operate()方法,输出:[brand] washing machine is washing [capacity]kg of clothesMicrowave.java:创建另一个继承自 Appliance 的具体类。微波炉有一个power字段(int),表示功率百分比。实现operate()方法,输出:[brand] microwave is heating at [power]% powerMain.java:使用多态把所有内容整合起来。你将收到五个输入:一个品牌名称、功率值、洗衣机容量、另一个品牌名称,以及微波炉功率级别。创建一个 WashingMachine 和一个 Microwave,然后将它们存入一个由Appliance引用组成的数组中。遍历这个数组,对每种家电,先使用getInfo()输出其信息,再调用operate()。
你将按以下顺序收到五个输入:第一个品牌(String)、第一个功率值(int)、以 kg 为单位的容量(int)、第二个品牌(String)和功率级别(int)。
输出应包含四行,每种家电各占两行,先显示信息,再显示其操作行为。注意,抽象类让你能够统一处理不同的家电,同时每种家电都能以自己独特的方式运行!
亲手试试
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取输入
String brand1 = scanner.nextLine();
int wattage1 = scanner.nextInt();
int capacity = scanner.nextInt();
scanner.nextLine(); // 读取并跳过换行符
String brand2 = scanner.nextLine();
int power = scanner.nextInt();
// TODO:使用 brand1、wattage1 和 capacity 创建一个 WashingMachine 对象
// TODO:使用 brand2、wattage1(或合适的功率值)和 power 创建一个 Microwave 对象
// TODO:创建一个 Appliance 引用数组,存入这两个对象
// TODO:遍历数组,对每个设备执行以下操作:
// 使用 getInfo() 打印设备信息
// 调用 operate()
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Java 在线编译器