在面向对象的概念中,所有的对象都是通过类来描述并创建的,但是有一种特殊的类,并不能用完整的信息来描述一个具体的对象,这样的类就是抽象类,不能完整描述对象相关信息的方法,通常称为抽象方法,也就是说,抽象类中需要包含抽象方法。
例如:
几何图形中有三角形,圆形,矩形,多边形的我们通常称为形状,形状就是对各种具体几何图形的模糊化,抽象化的通称,但形状本身又不能归结于某一个具体的几何图形,假如说形状就是三角形,这样的定义显然与现实不符,形状都具有面积,但是不同具体形状的面积有不同的计算方法,如果形状不能具体化,那么面积就无法计算,如果将形状表现为抽象,那么面积就是其中的抽象方法。
而抽象类一般作为父类,在抽象类中定义抽象方法,并交给抽象类的子类去实现抽象方法,也就是说在抽象类的各个子类中去定义完善某个具体对象的描述。
抽象方法是一种“特殊”的方法,该方法只有方法的定义部分(只有方法头)而没有方法的实现部分(没有方法体),在访问权限和返回类型之间需要用abstract关键字进行修饰。
定义格式如下:
权限修饰符 abstract returntype 方法名([参数列表]);
注意:
1:抽象方法只有方法头部并以“;”结束,没有方法体,所以后面不能有"{}"
2:构造方法不能被定义为抽象方法。
3:抽象类在定义时需要在class前添加abstract关键字修饰,类体中至少包含一个抽象方法,其余内容和普通方法一样,也可以定义普通常量,普通方法等。
定义格式如下:
[权限修饰符] abstract class 类名称{
成员属性;
常量;
构造方法([参数列表])//构造方法
{
..........}
[权限修饰符] returntype 方法名([参数列表])//普通方法
{
..........}
abstract returntype 方法名([参数列表])//抽象方法
{
..........}
}
1:由于抽象类是需要被子类继承的,所以抽象类不能使用final关键字修饰。
2:抽象类中定义的抽象方法是要被子类覆盖的,所以抽象方法不能用final关键字修饰,而且抽象类的访问权限不能是private。
3:抽象方法不能被static关键字修饰,抽象方法必须是实例方法。
4:抽象类不能用new运算符创建它的对象。
抽象类本身不能实例化,抽象类必须要有子类来继承它,否则抽象类就失去了存在的意义。
由于抽象类的子类实现了抽象类的抽象方法,从多态的角度讲,一般通常都是定义抽象类的引用指向抽象类子类的实例,自动完成上转型,因此,使用抽象类是对象多态性的一个很好的体现。
举例:
//Animal是抽象类[父类] Sheep是抽象类的子类[父类]
//通过上转型方式定义抽象类的子类对象
Aninmal sheep1=new Sheep();
关于抽象类的应用,这里我使用我们的实验中的一个进行作为例子:
-----顾客就餐实验:

首先我们先对实验内容进行分析,根据上图,很清楚的表明了Restaurant为继承类,也就是所谓的父类,其中它包含了3个抽象方法和一个普通方法,但这些方法的数量并不是一成不变的,我们可根据自己的理解进行调整。
对于问候或者加工这种无论是什么餐厅都是相同的,那么我们就将其写在父类中,而对于菜品的种类和点菜过程这种应写在不同的子类中。
代码如下所示;
package Restuarant;
abstract class restuarant {
//实验内容要求的抽象类
public abstract void pay();
public abstract void order();
public abstract void repast();
public void message(){
//新增普通方法
System.out.println("顾客用餐完毕,请通知服务人员尽快打扫对应的餐桌!");
}
public void process(){
//实验内容要求的普通类
System.out.println("您所点的菜品正在准备,请耐心等待!");
System.out.println("----------------");
System.out.println("菜品制作完成");
}
}
上文我们说过,抽象类本身不能实例化,抽象类必须要有子类来继承它,否则抽象类就失去了存在的意义,那么接下来我们就创建它的子类。
首先子类必须重写父类所有的抽象方法,当然子类也可以创建属于自己的变量和方法。
package Restuarant;
import java.util.Scanner;
public class Pizza extends restuarant{
double A=29.9;
double B=19.7;
double C=49.8;
double D=9.9;
double sum=0.0;
public double getSum() {
return sum;
}
public void setSum(double sum) {
this.sum = sum;
}
public double getD() {
return D;
}
public void setD(double d) {
D = d;
}
public double getC() {
return C;
}
public void setC(double c) {
C = c;
}
public double getB() {
return B;
}
public void setB(double b) {
B = b;
}
public double getA() {
return A;
}
public void setA(double a) {
A = a;
}
public void show_pizza() {
//子类特有的方法
System.out.println("本店菜品如下:");
System.out.println("1-双人套餐:"+A+",2-单人套餐:"+B+",3-全家桶:"+C+",4-儿童套餐:"+D);
}
//重写父类的
@Override
public void repast() {
System.out.println("----------------");
System.out.println("顾客正在2号餐厅吃饭......");
}
@Override
public void pay() {
System.out.println("请点击你需要的菜品号:结束点单请输入0!");
Scanner in = new Scanner(System.in);