1. 程式人生 > 實用技巧 >JAVA基礎 面向物件(五)抽象類 介面 內部類

JAVA基礎 面向物件(五)抽象類 介面 內部類

一、抽象類(abstract)

隨著繼承層次中一個個新子類的定義,類變得越來越具體,而父類則更一·般,更通用。類的設計應該保證父類和子類能夠共享特徵。有時將一個父類設計得非常抽象,以至於它沒有具體的例項,這樣的類叫做抽象類。

說明:子類的物件都已經很具體了,什麼功能都能實現了,完全不用再建立父類的物件了,這樣的父類,就成了抽象類。

1.1 abstract關鍵字

abstract關鍵字只能用來修飾類和方法。(不能修飾屬性,構造器、final等)

(1)abstract 修飾類 即抽象類

abstract修飾類以後,這個類就成了抽象類,即不能例項化物件的類了。所有的事情交給他的子類去做,所以抽象類一定有子類,例項化子類的物件去完成相關開發操作

語法:

【許可權修飾符】 abstract class 類名 {}

說明:雖然抽象類沒法例項化了,但是還是需要提供構造器(區分介面,介面沒有構造器,就是因為沒子類,又沒法例項化),因為抽象類的子類會通過super繼承這個抽象類的屬性和方法。

(2)abstract 修飾方法 抽象方法

abstract修飾方法以後,這個方法就成了抽象方法,即只有方法宣告,沒有方法體。抽象方法的方法體是留給後代去實現的,因此,後代必須重新該抽象方法,除非後代繼續是抽象類。直到後代重寫了父輩們的所有抽象類方法後,後代才可以例項化物件。換句話說,如果子類沒有寫完父輩的所有抽象方法,那麼該子類也是抽象類(必須用abstract修飾)。

語法:【許可權修飾符】 abstract 返回值型別 方法名(形參列表); //注意 沒有{ },即沒有方法體

說明:既然沒有方法體,意味著物件或類沒法呼叫該抽象方法,自然意味著抽象方法一定要在抽象類裡面,即有抽象方法的類一定是抽象類。但是抽象類中可以沒有抽象方法,抽象類只是不讓這個類造物件而已。

既然必須在子類重寫抽象方法,顯然,抽象類不允許是私有private,要不其他類根本就看不到。

同理,抽象方法不允許是static的,因為static方法根本不能重寫,類方法各是各的,不會覆蓋。(因為static是類方法,每個類都可以有多個子類,子類繼承父類方法的時候,先從靜態開始,沒法覆蓋父類方法的,所以不能重寫)。

語法:public abstract 返回值型別 方法名(); //注意,抽象方法沒有方法體,所以沒有大括號{}

(3)抽象類使用場景

比如求幾何圖形面積。父類就是幾何圖形,定義長寬高,體積,面積。但是由於不知道幾何圖形是啥,所以沒法寫他的面積公式。就可以把父類幾何圖形寫成抽象類,讓子類(具體的矩形,圓,三角形),來重寫面積,周長公式。

或者比如乘坐某交通工具去美國,交通工具的燃油消耗率,行駛時間,都是根據具體交通工具而異,因此抽象交通工具,燃油消耗率,行駛時間等方法,讓子類(具體的飛機,輪船),來重寫這些方法。

抽象類具有多型性:即可以 抽象類 類名 = new 子類(); 然後 類名.子類方法();

擴充套件:匿名子類 (綜合匿名物件)

所謂匿名,就是隻能呼叫一次,就是為了省事。

匿名子類,就是一個沒有名字的子類。抽象類 + 重寫抽象類中的方法,就成了一個匿名子類。

語法: 抽象父類 類名 = new 抽象父類空參構造器(){ //子類什麼名字不知道,這裡的類名是父類型別,多型性體現

抽象父類中的抽象方法(形參列表){方法體;} //匿名子類,需要重寫完抽象方法後,才可例項化出類名

}

說明:這裡的父類類名用了多型,其實例項化的是子類物件,不過子類沒有名字。匿名子類可以綜合匿名物件一起使用,形成一個大匿名,更省事。

exp:某方法(new 抽象類(){ //main中的某方法,直接呼叫一個匿名子類的匿名物件

抽象方法1() //匿名子類的匿名物件需要完成抽象類的抽象方法

抽象方法2(){

})

二、介面(Interface)

一方面,有時必須從幾個類中派生出一個子類,繼承它們所有的屬性和方法。但是, Java不支援多重繼承。有了介面,就可以得到多重繼承的效果。另一方面,有時必須從幾個類中抽取出一些共同的行為特徵,而它們之間又沒有is-a(籃球運動員is a 運動員)的關係,僅僅是具有相同的行為特徵而已。例如:滑鼠、鍵盤、印表機、掃描器、攝像頭、充電器、MP3機、手機、數碼相機、行動硬碟等都支援USB連線,但他們並不是is-a關係,而是has-a 關係,比如跨欄運動員和大學生都具備學習的技能,但顯然學習技能不是他們的父類。飛機、風箏、熱氣球都可以飛等等。這種has-a關係,就可以用介面。

· 介面就是規範,定義的是一組規則,體現了現實世界中“如果你是.則必須能.”的思想。繼承是一個"是不是"的關係,而介面實現則是"能不能"的關係。介面的本質是契約,標準,規範,就像我們的法律一樣。制定好後大家都要遵守。

2.1 介面的使用 interface關鍵字

在java中,介面和類是並列關係,(可以想象成介面是一種特別的類)

介面中,只能定義全域性常量和抽象方法(JDK7以前 穩定版),靜態方法、預設方法(JDK8以後)。

一個類可以實現多個介面。

介面可以繼承介面,並且可以多重繼承。

介面也能體現多型性。即 介面 類名 = new 實現類();

全域性常量:public static final 宣告的常量

抽象方法:public abstract 宣告的方法

語法: interface 介面名 【extends 介面1,介面2...】{ //介面可以繼承,並且是多重繼承

【public static final】 資料型別 變數名 【=預設值】;//由於介面中只能是全域性常量,因此public static final 可以省略

【public abstract】返回值型別 方法名();//抽象方法沒有方法體,所以沒有大括號

}

說明:介面中不能定義構造器,因為介面是has-a關係,沒有子類,同時意味著介面不可以例項化(又沒子類,又不能例項化,那自然不用構造器了)。為了實現介面的價值,java讓類(非子類)去實現介面的價值(implements),這個類就是實現類。如果實現類覆蓋了介面中的所有抽象方法,則此實現類就可以例項化。如果實現類沒有覆蓋完介面中的所有方法,則此實現類仍為抽象類。

語法:class 類名 【extends 父類 】implements 介面1【,介面2...】{ }

exp: interface Flyable{

int MAX_SPEED = 7900; //省略了【public static final】

void abstract void fly(); //抽象方法fly(),沒有大括號,等實現類來重寫。省略了【public abstract】

}

class Plane implements Flyable{ //實現類Plane

public void fly(){ //重寫介面中的fly()方法,此時可以構造物件

System.out.println("蝴蝶飛飛");}

Java類可以實現多個介面。