抽象类
由于多态的存在,每个子类都可以重写父类的方法,例如:
java
class GeometricObject {
public void getPerimeter() {
System.out.println("计算周长");
}
public void getArea() {
System.out.println("计算面积");
}
}
class Circle extends GeometricObject {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public void getPerimeter() {
System.out.println("圆的周长是:" + 2 * Math.PI * radius);
}
@Override
public void getArea() {
System.out.println("圆的面积是:" + Math.PI * radius * radius);
}
}
思考:如果父类
GeometricObject
中的getPerimeter()
方法没有实际意义, 能不能去掉方法中的执行语句呢?
在这种场景下,如果父类的方法本身不需要实现任何功能,仅仅是为了定义方法签名,目的是让子类去重写它。
那么,可以将父类和父类中的方法声明为抽象方法:
java
abstract class GeometricObject {
public abstract void getPerimeter();
public abstract void getArea();
}
class Circle extends GeometricObject {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public void getPerimeter() {
System.out.println("圆的周长是:" + 2 * Math.PI * radius);
}
@Override
public void getArea() {
System.out.println("圆的面积是:" + Math.PI * radius * radius);
}
}
抽象类
如果一个 class
类中定义了方法,但方法内部没有具体执行代码,这个方法就是抽象方法,抽象方法用 abstract 关键词修饰。
因为抽象方法无法直接执行,因此抽象方法所在的父类也必须声明为抽象类(abstract class)。
java
abstract class GeometricObject {
public abstract void getPerimeter();
public abstract void getArea();
}
注意
abstract
定义的 抽象方法 不能被实例化:
java
GeometricObject p1 = new GeometricObject(); //❌报错: 无法实例化
抽象类本质
上层代码只定义规范(如:
abstract class GeometricObject
);具体的业务逻辑有子类重写的方法去实现,父类和调用者并不需要关心;
abstract不能搭配的关键字
abscract 抽象类没有方法体,因此不能与一下 4 个关键字一起使用:
关键字 | 原因 |
---|---|
private 私有方法 | 私有方法子类访问不到,无法实现重写 |
静态方法 | 静态方法可以使用 Person.run() 的方式调用方法,而抽象类没有方法体,所以不能搭配 |
final 修饰的方法 | final 修饰的方法不能被子类继承,无法实现重写 |
final 修饰的子类 | final 修饰的方法不能被子类继承,无法实现重写 |
模板方法设计
模板方法设计 就是当类中的一部分功能是确定的,而另一部分功能是不确定的,这时候可以把不确定的部分暴漏出去,让子类按照业务单独实现逻辑。
示例:银行中有很多客户要办事,每个人办事都有三个步骤,
- 排队取号 (功能确定)
- 办理自己独有的业务,如想取钱、想汇款、想存款等等,每个人想办的业务各不相同 (功能不确定,需要子类单独实现)
- 反馈评分 (功能确定)
java
public static void main(String[] args) {
Person p = new Person();
p.waiting(); //排队取号中...
p.process(); //我要汇款100万!
p.feedback(); //请反馈评分...
System.out.println();
Student s = new Student();
s.waiting(); //排队取号中...
s.process(); //我想要取点生活费...
s.feedback(); //请反馈评分...
}
abstract class Bank {
public void waiting() {
System.out.println("排队取号中...");
}
/** 执行的过程根据子类业务单独实现 */
public abstract void process();
public void feedback() {
System.out.println("请反馈评分...");
}
}
class Person extends Bank {
@Override
public void process() {
System.out.println("我要汇款100万!");
}
}
class Student extends Bank {
@Override
public void process() {
System.out.println("我想要取点生活费...");
}
}