文章目录
如果自下而上在类的继承层次结构中上移,位于上层的类更具有通用性,甚至可能更加抽象。从某种角度看, 祖先类更加通用, 只是将它作为派生其他类的基类,而不作为想使用的特定的实例类。
抽象方法和抽象类
抽象方法和抽象类必须使用 abstract 修饰符来定义,有抽象方法的类只能被定义成抽象类,抽象类里可以没有抽象方法 。
抽象方法和抽象类的规则如下 。
- 抽象类必须使用 abstract 修饰符来修饰,抽象方法也必须使用 abstract 修饰符来修饰,抽象方法不能有方法体。
- 抽象类不能被实例化,无法使用 new 关键字来调用抽象类的构造器创建抽象类的实例 。 即使抽象类里不包含抽象方法,这个抽象类也不能创建实例。
- 抽象类可以包含成员变量、方法(普通方法和抽象方法都可以)、构造器、初始化块、内部类(接口、枚举) 5 种成分 。 抽象类的构造器不能用于创建实例, 主要是用于被其子类调用。
- 含有抽象方法的类(包括直接定义了 一个抽象方法;或继承了 一个抽象父类,但没有完全实现父类包含的抽象方法;或实现了一个接口,但没有完全实现接口包含的抽象方法三种情况)只能被定义成抽象类 。
抽象类实例
public class Main { public static void main(String[] args) { Person p = new Student(); p.run(); } } //抽象类Person abstract class Person { //抽象类 public abstract void run(); } //抽象类子类 class Student extends Person { //抽象类子类必须实现父类抽象方法 @Override public void run() { System.out.println("Student.run"); } }
抽象类的作用
抽象类不能创建实例,只能当成父类来被继承。
从语义的角度来看,抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象。从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的模板,从而避免了子类设计的随意性。抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会大致保留抽象类的行为方式。
如果编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,这就是一种模板模式,模板模式也是十分常见且简单的设计模式之一 。
下面再是一个个模板模式的范例,在这个范例的抽象父类中,父类的普通方法依赖于一个抽象方法,而抽象方法则推迟到子类中提供实现 。
模板模式范例-抽象父类
public abstract class SpeedMeter{ // 转速 private double turnRate; public SpeedMeter() {} // 把计算车轮周长的方法定义成抽象方法 public abstract double calGirth() ; public void setTurnRate(double turnRate){ this.turnRate = turnRate ; } //定义计算速度的通用算法 public double getSpeed(){ // 速度等于周长*转速 return calGirth () * turnRate; } }
模板模式范例-子类
public class CarSpeedMeter extends SpeedMeter{ private double radius; public CarSpeedMeter(double radius){ this.radius = radius ; } //实现父类抽象方法 public double calGirth(){ return radius * 2 * Math.PI ; } public static void main(String[] args){ //既可创建CarSpeedMeter 类的对象,也可通过该对象来取得当前速度 CarSpeedMeter csm = new CarSpeedMeter(O.34) ; csm.setTurnRate(15) ; System.out.println(csm . getSpeed()) ; } }
SpeedMeter 类里提供了速度表的通用算法 , 但一些具体的实现细节则推迟到其子类 CarSpeedMeter类中实现 。 这也是一种典型的模板模式。
模板模式在面向对象的软件中很常用,其原理简单,实现也很简单 。 下面是使用模板模式的一些简单规则 。
- 抽象父类可以只定义需要使用的某些方法,把不能实现的部分抽象成抽象方法,留给其子类去实现 。
- 父类中可能包含需要调用其他系列方法的方法,这些被调方法既可以由父类实现,也可以由其子类实现 。 父类里提供的方法只是定义了 一个通用方法,其实现也许并不完全由自身实现,而必须依赖于其子类的辅助 。
当使用了抽象的思想后:调用者只需关心抽象方法的定义,不必关心子类的具体实现。
参考:
【1】:《疯狂Java讲义》
【2】:《Java核心技术 卷一》
【3】:https://www.liaoxuefeng.com/wiki/1252599548343744/1260456371027744