Java 抽象類
本小節(jié)我們將學(xué)習(xí) Java 中的抽象類,你將了解到抽象類的概念和特點(diǎn),抽象類在程序設(shè)計時的應(yīng)用場景,什么是抽象方法,抽象方法有什么特點(diǎn),如何聲明一個抽象方法等內(nèi)容。
1. 概念和特點(diǎn)
在面向?qū)ο蟮母拍钪校械膶ο蠖际峭ㄟ^類來描繪的,但是反過來,并不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。
值得注意的是,一個抽象類不能直接實例化,但類的其他功能依然存在;既然不能被實例化,那么它必須被繼承才能被使用。
2. 為什么需要抽象類
當(dāng)某個父類只知道其子類應(yīng)該包含什么方法,但不知道子類如何實現(xiàn)這些方法的時候,抽象類就派上用場了。使用抽象類還有一個好處,類的使用者在創(chuàng)建對象時,就知道他必須要使用某個具體子類,而不會誤用抽象的父類,因此對于使用者來說,有一個提示作用。
例如,父類 Pet
被子類 Cat
和 Dog
繼承,并且都重寫了父類的 eat
方法:
class Pet {
// 定義方法 eat
public void eat() {
System.out.println("寵物都會吃東西");
}
}
class Dog extends Pet { // 繼承父類
// 重寫父類方法 eat
@Override
public void eat() {
System.out.println("狗狗吃狗糧");
}
}
class Cat extends Pet { // 繼承父類
// 重寫父類方法 eat
@Override
public void eat() {
System.out.println("貓貓吃貓糧");
}
}
小貓類、小狗類這些子類都重寫了寵物類中的 eat
方法,我們知道每種寵物都有吃的行為,寵物表示了一個抽象的概念。那么寵物類的實例化和方法調(diào)用就沒有了實際意義:
Pet pet = new Pet();
pet.eat();
我們知道了抽象類不能被實例化,此時可以將父類設(shè)定為抽象類,使用 abstract
關(guān)鍵字來聲明抽象類,abstract
關(guān)鍵字必須放在 class
關(guān)鍵字前面 :
// 聲明抽象類
abstract class Pet {
...
}
如果你嘗試實例化抽象類 Pet
,編譯器將會報錯:
Pet.java:4: 錯誤: Pet是抽象的; 無法實例化
new Pet();
^
1 個錯誤
使用抽象類,我們既可以通過父類和子類的繼承關(guān)系,來限制子類的設(shè)計隨意性,也可以避免父類的無意義實例化。
3. 抽象方法
抽象類中可以包含抽象方法,它是沒有具體實現(xiàn)的方法。換句話說,與普通方法不同的是,抽象方法沒有用 {}
包含的方法體。
抽象類可以定義一個完整的編程接口,從而為子類提供實現(xiàn)該編程接口所需的所有方法的方法聲明。抽象類可以只聲明方法,而不關(guān)心這些方法的具體實現(xiàn),而子類必須去實現(xiàn)這些方法。
上面我們將 Pet
父類改為了抽象類,其中包含了 eat
方法的具體實現(xiàn),而實際上這個方法是不需要具體實現(xiàn)的,每種寵物都有各自的具體實現(xiàn)。此時,就可以將 eat
方法改為抽象方法:
abstract class Pet {
abstract void eat();
}
我們可以看到抽象方法使用 abstract
關(guān)鍵字聲明,它沒有方法體,而直接使用 ;
結(jié)尾。
子類必須實現(xiàn)父類中的抽象方法,假如 Dog
類繼承了抽象類 Pet
,但沒有實現(xiàn)其抽象方法 eat
:
class Dog extends Pet {
}
編譯執(zhí)行代碼,將會報錯:
Dog.java:1: 錯誤: Dog不是抽象的, 并且未覆蓋Pet中的抽象方法eat()
public class Dog extends Pet {
^
1 個錯誤
上述報錯中可知,如果我們不想在 Dog
中重寫抽象方法 eat()
,那么可以將 Dog
也改為抽象類:
abstract class Dog extends Pet {
}
抽象方法不能是 final
、static
和 native
的;并且抽象方法不能是私有的,即不能用 private
修飾。因為抽象方法一定要被子類重寫,私有方法、最終方法以及靜態(tài)方法都不可以被重寫,因此抽象方法不能使用 private
、final
以及 static
關(guān)鍵字修飾。而 native
是本地方法,它與抽象方法不同的是,它把具體的實現(xiàn)移交給了本地系統(tǒng)的函數(shù)庫,沒有把實現(xiàn)交給子類,因此和 abstract
方法本身就是沖突的。
4. 小結(jié)
可以使用 abstract
關(guān)鍵字聲明抽象類或抽象方法。
抽象類不能被實例化,抽象類中的方法必須被非抽象子類實現(xiàn),它必須被繼承才能被使用。
抽象類中不一定包含抽象方法,但抽象方法一定在抽象類中。