1、定义
- 抽象方法:只有方法名字,没有具体方法实现的方法
- 抽象类:有抽象方法的类即为抽象类
2、规则
(1)抽象方法和抽象类必须使用abstract修饰符来修饰
(2)有抽象方法的类必须为抽象类、但抽象类里可以没有抽象方法
(3)抽象类不可被实例化,无法使用new关键字调用抽象类的构造器来创建抽象类的实例。只能当做父类被其他子类继承,并且子类要实现里面的抽象方法
(4)抽象类里可以有成员变量、方法(抽象方法和普通方法)、构造器、初始化块、内部类(接口、枚举)5种成分,其中构造器不能用于创建实例,只是用来被子类调用
(5)如果一个类:直接定义了抽象方法、或继承一个抽象父类,但并没有完全实现该父类的所有抽象方法、或实现一个接口,但并没有完全实现接口内包含的所有抽象方法,这种类只能被定义成抽象类
抽象方法的定义方式:将普通方法的方法体去掉,在后面加上分号即可
public abstract class Test{
public abstract void info(); //抽象方法
}
注意:public void info(){} 这是一个普通的方法,不是抽象方法,只是该方法的方法体为空,即什么也不做
抽象类的定义方式:只要在类前加上abstract修饰符即可
//定义一个形状抽象类
abstract class Shape{
private String color;
//color的setter和getter方法
public void setColor(String color) {
this.color=color;
}
public String getColor() {
return this.color;
}
//定义一个计算周长的抽象方法
public abstract double callPerimeter();
//定义一个形状的抽象方法
public abstract String getType();
//定义构造器,为了给子类调用
public Shape() {}
public Shape(String color) {
this.setColor(color);
}
}
//定义一个普通的三角形类
class Triangle extends Shape{
//定义三角形的三边
private double a;
private double b;
private double c;
//三角形必须满足:两边之和大于第三边
public void setSides(double a,double b,double c) {
if(a>b+c || b>a+c || c>a+b) {
System.out.println("三角形的三个边长度输入不满足条件");
return;
}
this.a=a;
this.b=b;
this.c=c;
}
public Triangle(String color,double a,double b,double c) {
super(color); //调用父类抽象类的构造器
this.setSides(a,b,c);
}
//重写计算周长的方法,实现父类的抽象方法
public double callPerimeter() {
return a+b+c;
}
//重写形状的方法,实现父类的抽象方法
public String getType() {
return getColor()+"三角形";
}
}
//定义一个普通的圆形类
class Circle extends Shape{
//定义圆的半径
private double radius;
//radius的setter和getter方法
public void setRadius(double radius) {
this.radius=radius;
}
public double getRadius() {
return this.radius=radius;
}
//Circle的构造器
public Circle(String color,double radius) {
super(color);
this.setRadius(radius);
}
//重写计算周长的方法,实现父类的抽象方法
public double callPerimeter() {
return 2*Math.PI*radius;
}
//重写形状方法,实现父类的抽象方法
public String getType() {
return getColor()+"圆";
}
}
public abstract class Test{
public static void main(String[] args) {
Shape s1=new Triangle("黑色",3,4,5);
Shape s2=new Circle("红色",2);
System.out.println(s1.callPerimeter());
System.out.println(s1.getType());
System.out.println(s2.callPerimeter());
System.out.println(s2.getType());
}
}
输出结果:
12.0
黑色三角形
12.566370614359172
红色圆
上面的程序中,使用了Shape类型的引用变量来指向实际的子类对象,从这里也可以看出明显的多态现象:同一个类(Shape类)的多个实例(s1、s2),在调用相同的方法(callPerimeter()和getType())时,呈现出不同的结果。
3、注意点
(1)final修饰一个类和方法时,表明该类不能被继承、该方法不可被重写;而abstract修饰一个类、方法时,表明该类是抽象类,必须被子类继承、该方法是抽象方法,必须由子类重写;故final和abstract不可同时出现
(2)abstract不能修饰构造器、成员变量、局部变量
(3)static和abstract不能同时修饰一个方法,即没有所谓的抽象类方法(但是可以同时修饰内部类)
(4)abstract修饰的抽象方法必须被子类重写,因此不能使用private修饰,即private和abstract不可同时修饰一个方法
4、设计方法:模板模式
抽象类体现了一种模板模式的设计,父类提供多个子类的通用方法,具体的实现留给每一个子类。