当编写一个类时,常常会为该类定义一些方法,这些方法用于描述该类的行为方式,那么这些方法都有具体的方法体。但在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法知道这些子类如何实现这些方法。例如定义了一个Shape类,这个类应该提供一个计算周长的方法calPerimeter(),但不同Shape子类对周长的计算方法时不一样的,即Shape类无法准确地知道其子类计算周长的方法。
既然Shape类不知道如何实现calPerimeter()方法,那么久干脆不要管它了!这不是一个好思路:假设有个Shape引用变量,该变量实际上引用到Shape子类的实例,那么这个Shape变量就无法调用calPerimeter()方法,必须将其强制转换为其子类类型,才可调用calPerimeter()方法,这就降低了程序的灵活性。
如何既能让Shape类里包含calPerimeter()方法,又无需提供其方法实现呢?使用抽象方法即可满足该要求:抽象方法只有方法签名,没有方法实现的方法。
一、抽象方法和抽象类
抽象方法和抽象类必须使用abstract修饰符来定义,有抽象方法的类只能被定义成抽象类,抽象类里可以没有抽象方法。
抽象方法和抽象类的规则如下:
①抽象类和抽象方法必须使用abstract修饰符来修饰。
②抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例,抽象类里不包含抽象方法
③抽象类可以包含成员变量、方法(普通方法和抽象方法都可以)、构造器、初始化块、内部类(接口、枚举)5种成分。抽象类的构造器不能用于创建实例,主要是用于被其子类调用。
④含有抽象方法的类(包括直接定义了一个抽象方法;或直接继承了一个抽象父类,但没有完全实现父类包含的抽象方法;或实现了一个接口,但没有完全实现接口包含的抽象方法三种情况)只能被定义成抽象类。
注意:归纳起来,抽象类可用“有得有失”4个字来描述。“得”指的是抽象类多了一个能力:抽象类可以包含抽象方法;“失”指的是抽象类失去了一个能力:抽象类不能被实例化。
定义抽象方法只需在普通方法上增加abstract修饰符,并把普通方法的方法体(也就是方法后花括号括起来的部分)全部去掉,并在方法后增加分号即可。
注意:
抽象方法和空方法体的方法不是同一个概念。例如,public abstract void test();是一个抽象方法,它根本没有方法体,即方法体定义后面没有一对花括号;但public void test() {}方法是一个普通方法,只是方法体为空,即它的方法体什么也不做,因此这个方法不可使用abstract来修饰。
定义抽象类只需在普通类上增加abstract修饰符即可。甚至一个普通类(没有包含抽象方法的类),增加abstract修饰符后也将变成抽象类。
下面定义一个Shape抽象类
public abstract class Shape
{
{
System.out.println("执行Shape的初始化块");
}
private String color;
//定义一个计算周长的抽象方法
public abstract double calPerimeter();
//定义一个返回形状的抽象方法
pub