面向抽象编程
在设计程序时,经常会使用到abstract类,其原因是,abstract类只关心操作,而不关心这些操作具体的实现细节,可以使程序的设计者把主要精力放在程序的设计上,而不必拘泥于细节的实现(将这些细节留给子类的设计者),即避免设计者把大量的时间和精力花费在具体的算法上。细节应当由抽象类的非抽象子类去实现,这些子类可以给出具体的实例,来完成程序功能的具体实现。在设计一个程序时,可以通过在abstract类中声明若干个abstract方法,表明这些方法在整个系统设计中的重要性,方法体的内容细节由它的非abstract子类去完成。
所谓面向抽象编程,是指当设计某种重要的类时,不让该类面向具体的类,而是面向抽象类,即所设计类中的重要数据是抽象类声明的对象,而不是具体类的声明的对象。
以下通过一个简单的问题来说明面向抽象编程的思想。
public abstract class Geometry {
public abstract double getArea();
}
public class Circle extends Geometry{
double r;
Circle(double r){
this.r=r;
}
public double getArea() {
return(3.14*r*r);
}
}
public class Rectangle extends Geometry{
double a,b;
Rectangle(double a,double b){
this.a=a;
this.b=b;
}
public double getArea() {
return a*b;
}
}
public class Pillar {
Geometry bottom; //bottom是抽象类Geometry声明的变量
double height;
Pillar (Geometry bottom,double height){
this.bottom=bottom;
this.height=height;
}
public double getVolume() {
if(bottom==null) {
System.out.println("没有底,无法计算体积");
return -1;
}
return bottom.getArea()*height; //bottom可以调用子类重写的getArea方法
}
}
面向接口编程
抽象类最本质的特性是可以包含抽象方法,这一点和接口类似,只不过接口中只有抽象方法而已。抽象类将其抽象方法的实现交给其子类,而接口将其抽象方法的实现交给实现该接口的类。在设计程序时,学习怎样面向接口去设计程序。接口只关心操作,但不关心这些操作的具体实现细节,可以使我们把主要精力放在程序的设计上,而不必拘泥于细节的实现。也就是说,可以通过在接口中声明若干个abstract方法,表明这些方法的重要性,方法体的内容细节由实现接口的类去完成。使用接口进行程序设计的核心思想是使用接口回调,即接口变量存放实现该接口的类的对象的引用,从而接口变量就可以回调类实现的接口方法。利用接口也可以体现程序设计的“开-闭原则”,即对扩展开放,对修改关闭。例如,程序的主要设计者可以设计出如下图所示的一种结构关系。
从下图可以看出,当程序再增加实现接口的类(由其他设计者去实现),接口变量variable所在的类不需要做任何修改,就可以回调类重写的接口方法。