抽象的概念
- 抽象類和抽象方法是面向?qū)ο缶幊讨械闹匾拍睿糜趯?shí)現(xiàn)抽象和繼承的特性。
- 抽象類是不能被實(shí)例化的類,通常用作其他類的基類。
- 抽象方法是在抽象類中聲明但沒(méi)有具體實(shí)現(xiàn)的方法,需要在子類中實(shí)現(xiàn)具體的功能。
抽象類的用途
假設(shè)我們開(kāi)了一個(gè)汽車玩具廠,現(xiàn)在要造奔馳和寶馬系列玩具。這兩種玩具的功能基本是一致,只是車的喇叭音樂(lè)不同。
由于只是車的內(nèi)置喇叭(trumpet) 不同,那么我們?cè)斓臅r(shí)候,我們首先開(kāi)發(fā)一套車的模板 (Car) 即可,車的骨架、內(nèi)部零件什么的都用一樣的。生產(chǎn)奔馳(Benchi) 系列的車,我們?nèi)?strong>奔馳車間給他裝上奔馳的內(nèi)置喇叭 (Benchi extends Car) ;生產(chǎn)寶馬系列的車,我們?nèi)?strong>寶馬(Baoma) 車間給他裝上寶馬的內(nèi)置喇叭 (Baoma extends Car)。
現(xiàn)在,我們奔馳系列的車模板和寶馬系列的車模板就造好了,出廠每一個(gè)車的時(shí)候,給車模套上車殼就完工了。
我們把生產(chǎn)汽車模板的過(guò)程抽象成一個(gè)Car類。
JAVA復(fù)制代碼abstract class Car {
String name;
public Car(String name){
this.name = name;
}
// 每個(gè)車都可以跑
void run(){
System.out.println(this.name + "跑起來(lái)了");
}
// 每個(gè)車的喇叭
abstract void trumpet()
}
由于每個(gè)車都必須有喇叭,因此trumpet方法是必須存在的。但每個(gè)系列的車?yán)炔煌虼耍贑ar類中,我們無(wú)法具體指明方法內(nèi)容(沒(méi)有寫(xiě)方法體)。這個(gè)trumpet方法就是一個(gè)抽象方法, 我們用abstract給他標(biāo)記一下。
由于Car缺少喇叭、車殼等零件(trumpet是抽象抽象方法,Car因此是抽象類),因此它無(wú)法直接生產(chǎn)玩具(不能實(shí)例化)。我們需要去不同車間繼續(xù)完善它 (只能被子類繼承、完善方法) 。
我們?nèi)ケ捡Y車間給他裝上奔馳的喇叭,奔馳系列玩具的車模就做好了。
java復(fù)制代碼class Bnechi extends Car {
public Bnechi(String name){
super(name);
}
public void trumpet(){
System.out.println("我是奔馳,啦啦啦");
}
}
然后,我們?nèi)汃R車間給他裝上喇叭,寶馬系列的玩具車模就做好了
scala復(fù)制代碼class Baoma extends Car {
public Baoma(String name){
super(name);
}
public void trumpet(){
System.out.println("我是寶馬,啦啦啦");
}
}
最后,我們?cè)诒捡Y和寶馬車間就可以不斷的生產(chǎn)玩具了。
上面的代碼中,我們定義了一個(gè)sountrumpetd方法,這是Car必須有的方法,但是每個(gè)子類(奔馳、寶馬)的這個(gè)方法是不同的,因此我們無(wú)法具體寫(xiě)成這個(gè)方法的內(nèi)容。
那么,這個(gè)sound方法就是一個(gè)抽象方法,對(duì)應(yīng)的,Car就是一個(gè)抽象類。Car是不完整的,因此它不能直接生產(chǎn)成一個(gè)玩具車 (不能實(shí)例化)。
我們需要用Car這個(gè)模板來(lái)完善我們的奔馳系列玩具
java復(fù)制代碼public class CarFactory {
public static void mAIn(String[] args) {
// 生產(chǎn)奔馳
Bnechi BCA = new Bnechi("奔馳A級(jí)");
BCA.run();
BCA.trumpet();
// 生產(chǎn)寶馬
Baoma BMW1 = new Baoma("寶馬1系");
BMW1.run();
BMW1.trumpet();
}
}
語(yǔ)法詳解
抽象類
抽象類使用abstract關(guān)鍵字進(jìn)行聲明,它可以包含抽象方法和普通方法。
它無(wú)法直接創(chuàng)建抽象類的實(shí)例,只能通過(guò)繼承它的子類來(lái)使用。抽象類通常用于定義類的共同特征和行為,而將具體的實(shí)現(xiàn)細(xì)節(jié)留給子類來(lái)完成。
示例代碼:
java復(fù)制代碼abstract class Car {
String name;
public Car(String name){
this.name = name;
}
// 普通方法
void run(){
System.out.println(this.name + "跑起來(lái)了");
}
// 抽象方法,子類需要實(shí)現(xiàn)具體的功能,不寫(xiě)函數(shù)體
abstract void trumpet()
}
- 聲明了一個(gè)String類型的變量name,表示車的名稱。
- 定義了一個(gè)構(gòu)造方法Car(String name) ,用于初始化車的名稱。
- 聲明了一個(gè)非抽象方法run() ,用于輸出車名并顯示它在跑。
- 聲明了一個(gè)抽象方法trumpet() ,沒(méi)有具體實(shí)現(xiàn),需要在子類中重寫(xiě)。
抽象方法
抽象方法是在抽象類中聲明但沒(méi)有具體實(shí)現(xiàn)的方法,它使用abstract關(guān)鍵字進(jìn)行聲明。抽象方法沒(méi)有方法體,只有方法簽名,子類必須實(shí)現(xiàn)這些抽象方法,否則子類也必須聲明為抽象類。
示例代碼:
java復(fù)制代碼abstract class Car {
String name;
public Car(String name){
this.name = name;
}
// 每個(gè)車都可以跑
void run(){
System.out.println(this.name + "跑起來(lái)了");
}
// 每個(gè)車的音樂(lè)
abstract void trumpet();
}
// 子類繼承父類
class Bnechi extends Car {
public Bnechi(String name){
super(name);
}
// 子類完善父類的抽象方法
public void trumpet(){
System.out.println("我是奔馳,啦啦啦");
}
}
// 子類繼承父類
class Baoma extends Car {
public Baoma(String name){
super(name);
}
// 子類完善父類的抽象方法
public void trumpet(){
System.out.println("我是寶馬,啦啦啦");
}
}
抽象類和抽象方法的使用場(chǎng)景:
- 當(dāng)某個(gè)類的對(duì)象不需要直接創(chuàng)建,而只作為其他具體類的基類模板時(shí),可以將該類聲明為抽象類。
- 當(dāng)多個(gè)類擁有相似的行為,但在具體實(shí)現(xiàn)上有所不同,可以將共同的行為定義在抽象類中,具體實(shí)現(xiàn)交給子類。
- 抽象類和抽象方法可以幫助實(shí)現(xiàn)多態(tài)性,即通過(guò)父類引用指向子類對(duì)象,便于統(tǒng)一處理不同子類的對(duì)象。