如果自下而上在类的继承层次结构中上移,位于上层的类更具有通用性,甚至可能更加抽象。从某种角度看, 祖先类更加通用, 只是将它作为派生其他类的基类,而不作为想使用的特定的实例类。
抽象方法和抽象类必须使用 abstract 修饰符来定义,有抽象方法的类只能被定义成抽象类,抽象类里可以没有抽象方法 。
抽象方法和抽象类的规则如下 。
抽象类实例
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