一,抽象类
1.概念
普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法、普通方法、static方法、常量和变量等内容。而抽象类是指在普通类的结构里面增加抽象方法的组成部分。
那么什么叫抽象方法呢?在所有的普通方法上面都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。而抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰。
而拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明。
抽象方法和抽象类的规则如下。
☆抽象类必须使用abstract修饰符来修饰,抽象方法也必须使用abstract修饰符来修饰,抽象方法不能有方法体。
☆抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例。即使抽象类里不含抽象方法这个抽象类也不能创建实例。
☆抽象类可以包含成员变量、方法(普通方法和抽象方法都可以)、构造器、初始化块、内部类(接口、枚举)5种成分。抽象类的构造器不能用于创建实例,主要是用于被其子类继承。
☆含有抽象方法的类(包括直接定义了一个抽象方法;或继承了一个抽象父类,但没有完全实现父类包含的抽象方法;或实现了一个接口,但没有完全实现接口包含的抽象方法三种情况)只能被定义成抽象类。
2.抽象类的使用
我们来看一个抽象类范例;
public abstract class Shape {
{
System.out.println("执行Shape的初始化块...");
}
private String color;
// 定义一个计算周长的抽象方法
public abstract double calPerimeter();
// 定义一个返回形状的抽象方法
public abstract String getType();
// 定义Shape的构造器,该构造器并不是用于创建Shape对象,而是用于被子类调用
public Shape() {}
public Shape(String color) {
System.out.println("执行Shape的构造器...");
this.color = color;
}
// 省略color 的setter 和getter 方法
}
抽象类不能用于创建实例,只能当作父类被其他子类继承
下面定义个三角形类,三角形类被定义成普通类,因此必须实现Shape类里的所有方法。
public class Triangle extends Shape {
// 定义三角形的三边
private double a;
private double b;
private double c;
public Triangle(String color, double a, double b, double c) {
super(color);
this.setSides(a, b, c);
}
public void setSides(double a, double b, double c) {
if (a >= b + c || b >= a + c || c >= a + b) {
System.out.println("三角形两边之和必须大于第三边");
}
this.a = a;
this.b = b;
this.c = c;
}
// 重写Shape的计算周长的抽象方法
public double calPerimeter() {
return a + b + c;
}
// 重写Shape类的返回形状的抽象方法
public String getType() {
return "三角形";
}
}
上面的Triangle类继承了Shape抽象类,并实现了Shape类中两个抽象方法,是一个普通类,因此可以创建
Triangle类的实例,可以让一个Shape类型的引用变量指向Triangle对象。
3.抽象类的作用
从前面的示例程序可以看出,抽象类不能创建实例,只能当成父类来被继承。它体现的是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽类的基础上进行扩展、改造,但子类总体上会大致保留抽象类的行为方式。
模板模式在面向对象的软件中很常用,其原理简单,实现也很简单。下面是使用模板模式的一些简单规则。
☆抽象父类可以只定义需要使用的某些方法,把不能实现的部分抽象成抽象方法,留给其子类去实现
☆父类中可能包含需要调用其他系列方法的方法,这些被调用方法既可以由父类实现,也可以由其子类实现。父类里提供的方法只是定义了一个通用算法,其实现也许并不完全由自身实现,而必须依赖于其子类的辅助。