一. 引出抽象方法
案例:求圆(circle),矩形(rectangle),三角形(triangle)的面积
class Graph
{
public Double getArea(){
return 0.0; // 默认返回0.0
}
}
class Circle extends Graph
{
private Double r ;//半径
Circle(Double r){
this.r = r;
}
public Double getArea(){
return Math.PI * r* r;
}
}
class Rectangle extends Graph
{
private Double width; //宽
private Double hight; // 高
Rectangle(Double width, Double hight){
this.width = width;
this.hight = hight;
}
public Double getArea(){
return width * hight;
}
}
class Rriangle extends Graph
{
private Double a;
private Double b;
private Double c;
Rriangle(Double a, Double b,Double c){
this.a = a;
this.b= b;
this.c = c;
}
// 故意不写求面积的方法
}
class AbstractDemo
{
public static void main(String[] args)
{
System.out.println(new Circle(10.0).getArea()); // 圆的面积
System.out.println(new Rectangle(1.0,3.0).getArea()); // 矩形的面积
System.out.println(new Rriangle(3.0,4.0,5.0).getArea()); // 三角形面积
}
}
---------- 运行java ----------
314.1592653589793
3.0
0.0
输出完成 (耗时 0 秒) - 正常终止
上述代码中存在的问题:
(1): 每一个图形都有面积,所在在Graph类中定义求面积的方法getArea没问题.。但是,不同的具体图形求面积的算法是不一样的,也就是说,每一个图形的子类都必须去覆盖getArea方法,如果不覆盖,应该语法报错,必须覆盖。
(2): 在图形类中定义了getArea方法,该方法不应该存在方法体,因为不同图形子类求面积算法不一样,父类真不知道该怎么写,所以应该提供无方法体。
二. 抽象方法
使用abstract修饰且没有方法体的方法叫做抽象方法.
特点:
(1) 使用抽象abstract修饰,方法没有方法体,留给子类去实现;
(2) 抽象方法修饰符不可以是private,final和static,因为:
- private:子类无法访问该方法,也就无法实现;
- final:阻止了该方法的实现;
- static:一旦用static修饰,就不能被子类重写实现;
(3) 抽象方法必须定义在抽象类或接口中。
一般地,习惯吧abstract写在方法修饰符的最前面,一看就知道是抽象方法。
三. 抽象类
使用abstract修饰的类就是抽象类
特点:
(1) 不能创建实例,即不能用new一个抽象类。即使创建出抽象类对象,调用抽象方法根本没意义。
abstract class Graph{
abstract public void getArea();
}
class AbstractDemo2 {
public static void main(String[] args) {
new Graph(); // 编译报错
}
}
---------- 编译java ----------
AbstractDemo2.java:11: 错误: Graph是抽象的; 无法实例化
new Graph();
^
1 个错误
输出完成 (耗时 0 秒) - 正常终止
(2) 抽象类可以不包含抽象方法(也就说抽象类可以包含普通方法,主要是留给子类调用的),若一旦包含抽象方法,该类必须是抽象类;
抽象类可以包含普通方法(留给子类调用的),抽象类是有构造器的(留给子类调用)
abstract class Graph
{
Graph(){} // 抽象类是存在构造器的
abstract public void getArea(); // 抽象方法(不带花括号)
public void doWork(){};// 普通方法(要带花括号)
}
class AbstractDemo2
{
public static void main(String[] args) {}
}
(3) 若子类没有实现/覆盖父类所有的抽象方法,那么子类也必须作为抽象类,也就是说抽象类必须要有个子类才有存在意义,才能完成抽象类的未尽事业!
(4) 构造方法不能都定义成私有的,否则不能有子类(创建子类对象前先调用父类构造方法)
(5) 抽象类不能使用final修饰,因为必须有子类,抽象方法才能得以实现。
(6) 抽象类是不完整的类,需作为基类功能才能的以实现。
注意:
- 1.定义抽象类时,一般我们起名习惯使用abstract作为前缀,让调用者一看就知道是抽象类。
- 2.抽象类中可以不存在抽象方法,如此这样没有太大的意义,但是可以防止外界创建对象,我们后发现有些工具类没有抽象方法,但是也使用abstract来修饰。
- 3.抽象类不能实例化!
抽象类和普通类的区别:
- 普通类有的成员(方法,字段,构造器)抽象类都有
- 抽象类不能创建对象,抽象类中可以包含抽象方法。
总结
1.抽象类必须有子类,有实现(子类或子子类等来实现)才有意义
2.对象必须完整–>抽象类所对应的不完整的对象是没有意义的.–>抽象类不能直接实例化,由非子类创建完整的对象