一. 引出抽象方法

案例:求圆(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.对象必须完整–>抽象类所对应的不完整的对象是没有意义的.–>抽象类不能直接实例化,由非子类创建完整的对象