在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的。
如果一个类没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
如:
说明:
① 矩形、三角形、圆形都是图形,因此和Shape类的惯性应该是继承关系;
② 虽然图形类Shape中也存在draw的方法,但由于Shape类并不是具体的图形,因此其内部的draw方法实际是没有办法实现的;
③ 由于Shape类没有办法描述一个具体的图形,导致其draw()方法无法具体实现,因此可以将Shape类设计为“抽象类”。
故我们发现,父类 Shape 中的 draw 方法好像并没有什么实际工作, 主要的绘制图形都是由 Shape的各种子类的 draw 方法来完成的。像这种没有实际工作的方法,我们可以把它设计成一个 抽象方法(abstract method), 包含抽象方法的类我们称为抽象类(abstract class)。
在Java中,一个类如果被 abstract 修饰称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。
// 抽象类:被abstract修饰的类
public abstract class Shape {
// 抽象方法:被abstract修饰的方法,没有方法体
abstract public void draw();
abstract void calcArea();
// 抽象类也是类,也可以增加普通方法和属性
public double getArea(){
return area;
}
protected double area; // 面积
}
注意:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法。
abstract class Shape {
//普通方法
public void draw() {
}
//抽象方法,可以不写具体的实现
public abstract void func();
}
public class Test2 {
public static void main(String[] args) {
Shape shape = new Shape(); //报错了
}
}
// 编译出错
Error:(30, 23) java: Shape是抽象的; 无法实例化
【抽象类和普通类的区别】
① 抽象类不能实例化;普通类可以。
② 抽象类中,可以包含非抽象方法和抽象方法;普通类只能包含非抽象方法。
抽象类存在的最大意义就是为了被继承,当一个普通类继承抽象方法时,这个子类必须重写抽象方法。
抽象类本身不能实例化,要想使用,只能创建该抽象类的子类,然后让子类重写抽象类中的抽象方法。
很多语法出现的意义就是为了防止出错! 抽象类也相当于多了一重编译器的校验。
使用抽象类的场景如上面的代码,实际工作是由子类完成的,那么此时如果不小心误用成父类了,使用普通类编译器是不会报错的;但是父类是抽象类,就会在实例化的时候提示错误,让我们尽早发现问题。