抽象類和抽象方法
抽想方法
所有的普通方法上面都會有一個“{}”,這個表示方法體,有方法體的方法一定可以被對象直接使用。而抽象方法,是指沒有方法體的方法,同時抽象方法還必須使用關鍵字abstract做修飾。
抽象類
如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。
抽象類除了不能實例化對象之外,類的其它功能依然存在,成員變量、成員方法和構造方法的訪問方式和普通類一樣。
由於抽象類不能實例化對象,所以抽象類必須被繼承,才能被使用。
在java中,使用 abstract class 來定義抽象類。
示例
1 abstract class AbstractClass{//定義一個抽象類 2 /** 3 * 普通方法 4 */ 5 public void fun(){ 6 System.out.println("存在方法體的方法"); 7 } 8 9 /** 10 * 抽象方法 沒有方法體,有abstract關鍵字做修飾 11 */ 12 public abstract void print(); 13 }
抽象類的使用原則如下:
(1)抽象方法必須為public或者protected(因為如果為private,則不能被子類繼承,子類便無法實現該方法),缺省情況下默認為public;
(2)抽象類不能直接實例化,需要依靠子類采用向上轉型的方式處理;
(3)抽象類必須有子類,使用extends繼承,一個子類只能繼承一個抽象類;
(4)子類(如果不是抽象類)則必須覆寫抽象類之中的全部抽象方法(如果子類沒有實現父類的抽象方法,則必須將子類也定義為為abstract類)。
注意:
- 如果一個類包含抽象方法,那么該類必須是抽象類。
- 任何子類必須重寫父類的抽象方法,或者聲明自身為抽象類。
最終,必須有子類實現該抽象方法,否則,從最初的父類到最終的子類都不能用來實例化對象。
1 abstract class AbstractClass{//定義一個抽象類 2 /** 3 * 普通方法 4 */ 5 public void fun(){ 6 System.out.println("存在方法體的方法"); 7 } 8 9 /** 10 * 抽象方法 沒有方法體,有abstract關鍵字做修飾 11 */ 12 public abstract void print(); 13 } 14 15 abstract class MidClass extends AbstractClass{ 16 /** 17 * 抽象方法 18 */ 19 public abstract void draw(); 20 } 21 22 23 class SubClass extends MidClass{ 24 @Override 25 public void print() { 26 System.out.println("打印"); 27 } 28 29 @Override 30 public void draw() { 31 System.out.println("畫畫"); 32 } 33 } 34 35 public class Abstract{ 36 public static void main(String[] args) { 37 /* 38 // 編譯錯誤 39 AbstractClass class1 = new AbstractClass(); 40 */ 41 SubClass subClass = new SubClass(); 42 subClass.print(); 43 subClass.draw(); 44 } 45 }
總結
1. 抽象類不能被實例化,如果被實例化,就會報錯,編譯無法通過。只有抽象類的非抽象子類可以創建對象。
2. 抽象類中不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
3. 抽象類中的抽象方法只是聲明(public或者protected),不包含方法體,就是不給出方法的具體實現也就是方法的具體功能。
4. 構造方法,類方法(用 static 修飾的方法)不能聲明為抽象方法。
5. 抽象類的子類必須給出抽象類中的抽象方法的具體實現,除非該子類也是抽象類。
抽象類和接口的區別
1、語法層面上的區別
1)抽象類可以提供成員方法的實現細節,而接口中只能存在public abstract 方法;
2)抽象類中的成員變量可以是各種類型的,而接口中的成員變量只能是public static final類型的;
3)接口中不能含有靜態代碼塊以及靜態方法,而抽象類可以有靜態代碼塊和靜態方法;
4)一個類只能繼承一個抽象類,而一個類卻可以實現多個接口。
2、設計層面上的區別
1)抽象類是對一種事物的抽象,即對類抽象,而接口是對行為的抽象。抽象類是對整個類整體進行抽象,包括屬性、行為,但是接口卻是對類局部(行為)進行抽象。舉個簡單的例子,飛機和鳥是不同類的事物,但是它們都有一個共性,就是都會飛。那么在設計的時候,可以將飛機設計為一個類 Airplane,將鳥設計為一個類 Bird,但是不能將 飛行 這個特性也設計為類,因此它只是一個行為特性,並不是對一類事物的抽象描述。此時可以將 飛行 設計為一個接口Fly,包含方法fly( ),然后Airplane和Bird分別根據自己的需要實現Fly這個接口。然后至於有不同種類的飛機,比如戰斗機、民用飛機等直接繼承Airplane即可,對於鳥也是類似的,不同種類的鳥直接繼承Bird類即可。從這里可以看出,繼承是一個 "是不是"的關系,而 接口 實現則是 "有沒有"的關系。如果一個類繼承了某個抽象類,則子類必定是抽象類的種類,而接口實現則是有沒有、具備不具備的關系,比如鳥是否能飛(或者是否具備飛行這個特點),能飛行則可以實現這個接口,不能飛行就不實現這個接口。
2)設計層面不同,抽象類作為很多子類的父類,它是一種模板式設計。而接口是一種行為規范,它是一種輻射式設計。什么是模板式設計?最簡單例子,大家都用過 ppt 里面的模板,如果用模板 A 設計了 ppt B 和 ppt C,ppt B 和 ppt C 公共的部分就是模板 A 了,如果它們的公共部分需要改動,則只需要改動模板 A 就可以了,不需要重新對 ppt B 和 ppt C 進行改動。而輻射式設計,比如某個電梯都裝了某種報警器,一旦要更新報警器,就必須全部更新。也就是說對於抽象類,如果需要添加新的方法,可以直接在抽象類中添加具體的實現,子類可以不進行變更;而對於接口則不行,如果接口進行了變更,則所有實現這個接口的類都必須進行相應的改動。