Skip to content

抽象类

由于多态的存在,每个子类都可以重写父类的方法,例如:

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(); //❌报错: 无法实例化

抽象类本质

  1. 上层代码只定义规范(如:abstract class GeometricObject);

  2. 具体的业务逻辑有子类重写的方法去实现,父类和调用者并不需要关心;

abstract不能搭配的关键字

abscract 抽象类没有方法体,因此不能与一下 4 个关键字一起使用:

关键字原因
private 私有方法私有方法子类访问不到,无法实现重写
静态方法静态方法可以使用 Person.run() 的方式调用方法,而抽象类没有方法体,所以不能搭配
final 修饰的方法final 修饰的方法不能被子类继承,无法实现重写
final 修饰的子类final 修饰的方法不能被子类继承,无法实现重写

模板方法设计

模板方法设计 就是当类中的一部分功能是确定的,而另一部分功能是不确定的,这时候可以把不确定的部分暴漏出去,让子类按照业务单独实现逻辑

示例:银行中有很多客户要办事,每个人办事都有三个步骤,

  1. 排队取号 (功能确定)
  2. 办理自己独有的业务,如想取钱、想汇款、想存款等等,每个人想办的业务各不相同 (功能不确定,需要子类单独实现)
  3. 反馈评分 (功能确定)
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("我想要取点生活费...");
  }
}

Released under the MIT License.