5.5.1 抽象方法和抽象类
抽象方法和抽象类的规则:
抽象方法和抽象类必须使用abstract修饰符来定义,有抽象方法的类只能被定义成抽象类,抽象类里可以没有抽象方法,抽象方法不能有方法体。
抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例。
抽象类可以包含成员变量,方法,构造器,初始化类,内部类。抽象类不能用于创建实例,主要是用于被其子类调用
含有抽象方法的类只能被定义成抽象类
抽象方法和空方法体不是同一个概念。public abstract void test();是一个抽象方法。public void test(){}是一个空方法体。
Shape.java
package code.shape;
public abstract class Shape{
{
System.out.println("执行Shape的初始化块...");
}
private String color;
public abstract double calPerimeter();
public abstract String getType();
public Shape(){
}
public Shape(String color){
System.out.println("执行Shape的构造器...");
this.color = color;
}
public void setColor(String color){
this.color = color;
}
public String getColor(){
return color;
}
}
Triangle.java
package code.shape;
import code.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("三角形两边之和必须大于等于第三边");
return;
}
this.a = a;
this.b = b;
this.c = c;
}
public double calPerimeter(){
return a+b+c;
}
public String getType(){
return "三角形";
}
}
Circle.java
package code.shape;
import java.lang.Math;
import code.shape.*;
public class Circle extends Shape{
private double radius;
public Circle(String color,double radius){
super(color);
this.radius = radius;
}
public void setRadius(double radius){
this.radius = radius;
}
public double calPerimeter(){
return 2*Math.PI*radius;
}
public String getType(){
return getColor() + "圆形";
}
public static void main(String []args){
Shape s1 = new Triangle("黑色",3,4,5);
Shape s2 = new Circle("红色",4);
System.out.println(s1.getType());
System.out.println(s1.calPerimeter());
System.out.println(s2.getType());
System.out.println(s2.calPerimeter());
}
}
执行Shape的初始化块…
执行Shape的构造器…
执行Shape的初始化块…
执行Shape的构造器…
三角形
12.0
红色圆形
25.132741228718345
当使用abstract修饰类时,表明这个类只能被继承;当使用abstract修饰方法时,表明这个方法必须由子类提供实现(即重写)。而final修饰的类不能被继承,final修饰的方法不能被重写。因此final和abstract永远不能同时使用。
static和abstract并不是绝对互斥,static和abstract不能同时修饰某个方法,但可以同时修饰内部类。
abstract方法不能定义为private访问权限。abstract和private不能同时修饰方法。
5.5.2 抽象类的作用
从语义的角度来看,抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象。
抽象类体现的就是一种模板模式的设计。
在上述Shape,Circle和Triangle三个类使用了模板模式,父类的普通方法依赖于一个抽象方法,而抽象方法则推迟到子类中实现。
SpeedMeter.java
package code.speed;
public abstract class SpeedMeter{
private double turnRate;
public SpeedMeter(){}
public void setTurnRate(double turnRate){
this.turnRate = turnRate;
}
public abstract double getRadius();
public double getSpeed(){
return java.lang.Math.PI * 2 *getRadius() * turnRate;
}
}
carSpeedMeter.java
package code.speed;
public class carSpeedMeter extends SpeedMeter{
public double getRadius(){
return 0.28;
}
public static void main(String[] args){
SpeedMeter sm = new carSpeedMeter();
sm.setTurnRate(15);
System.out.println(sm.getSpeed());
}
}
26.389378290154266
规则:
- 抽象父类可以只定义需要使用的某些方法,把不能实现的部分方法抽象成抽象方法,留给其子类去实现。
- 父类中可能包含需要调用其他系列方法的方法,这些被调方法既可以由父类实现,也可以由其子类实现。父类里提供的方法只是定义了一个通用算法,其实现也许并不完全由自身实现,而必须依赖于其子类的辅助。