java零基礎(chǔ)入門-面向?qū)ο笃?/b>(十二)? 抽象類
抽象類這個玩意,理解起來費點勁。我們從字面意思開始吧。
抽象一詞的本義是指人在認識思維活動中對事物表象因素的舍棄和對本質(zhì)因素的抽取。說人話就是刪除看的懂得,留下看不懂的。
應(yīng)用于美術(shù)領(lǐng)域,便有了抽象性藝術(shù)、抽象主義、抽象派等概念。
來看一個著名的抽象派作品。

84歲的美國藝術(shù)家羅伯特·雷曼1961年創(chuàng)作的油畫《無題》,以折合人民幣8000萬至1.2億元的價格拍賣。
我感覺這畫跟我家衛(wèi)生間的瓷磚有點像,莫非我家的還是個抽象派衛(wèi)生間不成...
至于抽象類,它和抽象畫還真的有點相似之處
抽象畫:我告訴你我畫了一幅畫,具體畫的啥,我也不知道!
抽象類:我告訴你我定義了一些方法,方法具體做什么,我也不知道!
為什么要抽象類
畫家分為很多流派,以我淺顯的藝術(shù)知識,大概分得清楚三個流派的畫家,抽象派,印象派,立體派。
現(xiàn)在確定了父類 - 畫家,然后三個子類 抽象派畫家 , 印象派畫家,立體派畫家去繼承畫家這個類。畫家類里面有一個方法,畫畫,這個方法是必須有的。
好了,問題出現(xiàn)了,當我們使用父類 - 畫家創(chuàng)建對象,然后調(diào)用 畫畫這個方法的時候,它應(yīng)該畫出來的是哪個流派的畫?
是不是懵圈了?你就給我個畫家,也沒問人家是哪一派的,就拉著人家畫畫,鬼知道他畫的啥。

這說明一個什么問題?如果我們將某一部分事物的特征抽取出來,定義成了父類,其實這個父類是具有指導性的,而不是可實現(xiàn)性。
說人話,你非要將畫家提出一個父類,那么就不要在父類里面實現(xiàn)方法,也就是不要在父類里面寫代碼邏輯。因為父類并不知道他自己被實例化以后,該如何實現(xiàn)方法。
比如這個畫家,如果不是畫家的子類,具體到某個流派的畫家,在畫家這個類里面實現(xiàn)畫畫這個方法是毫無意義的。他不知道該畫個什么流派的畫出來。我們只會使用子類重寫的畫畫方法,而不會使用父類的畫畫方法。

有同學肯定有疑問,既然我們不使用父類里面的畫畫方法,刪掉不就行了?只在子類里面寫畫畫的方法不就行了?
那么我請問你,你見過連畫畫都不會的畫家嗎?畫家這個類沒有畫畫這個方法,就算代碼不錯,你的類的設(shè)計就是錯的。類是對實際事物的抽象,這個是原則。
那該怎么做?
這時候就該抽象方法登場了。把畫畫這個方法定義成抽象方法,畫家父類并不實現(xiàn)任何代碼,而是留給子類去實現(xiàn)他。你是什么派的畫家,畫畫的方法就畫什么派的畫就行了。

看到了沒有,抽象方法的核心思想就是 啥也不做~ 具體要做的,用子類去實現(xiàn)抽象方法即可。
抽象類的清規(guī)戒律
1.抽象方法不能被調(diào)用。
2.一個類被定義為抽象類以后,就不能使用new關(guān)鍵字新建對象了。
3.抽象類的子類必須重寫抽象方法。
這三個規(guī)則放在一起,因為他們環(huán)環(huán)相扣。為了方便記憶,我們用代碼來講解。
首先看報錯情況。

1.因為抽象方法沒有方法體,啥也不干,所以不能調(diào)用抽象方法,因為這樣做毫無意義。
2.假設(shè)可以實例化抽象類,那么就可以用抽象類的對象去調(diào)用什么也干不了的抽象方法,這樣違背了第一條原則。
3.如果繼承了抽象類,而又不去重寫(實現(xiàn))抽象類的抽象方法,會發(fā)生什么?因為子類沒有實現(xiàn)父類的抽象方法,那么用子類對象就可以調(diào)用到父類的抽象方法,這樣也違背了第一條原則。

4.抽象類可以包含普通方法和構(gòu)造器。抽象類就是專門用來被子類繼承的,如果子類都有一個不必被重寫的方法,那么可以將它定義在父類里面,每個子類都可以調(diào)用他。構(gòu)造器也一樣,可以被子類復用。
比如畫家除了畫畫這個抽象方法以外,還可以有賣畫這個方法,上面那位大師的一幅畫可是賣了幾千萬。每個畫家都可以賣畫,自己不去實現(xiàn),就調(diào)用父類的方法。構(gòu)造器也是一樣,可以用super調(diào)用抽象類的構(gòu)造器,大家可以自己實現(xiàn)一下。
舉個栗子
說了半天抽象類,下面再舉個例子幫助大家更好的理解一下。
來來來,需求講解一下,現(xiàn)在要做三個功能,請假,加班,外出,原型圖如下。如果是你你會怎么做?
如果我們沒有一點點的抽象能力,肯定會說,這還不簡單,做三個功能唄。
但是我們現(xiàn)在可是學過抽象類的人了,怎么能做這么不優(yōu)雅的事,我們必須要有設(shè)計的概念。

我們觀察了原型圖以后,可以看到,紅色框中的內(nèi)容,是三個功能都有的。不管你是請假,外出,還是加班,都需要一個人來對你的請求進行審批。這個是必須的(前面有個紅色星星)。
而審批轉(zhuǎn)聊天功能和抄送功能都是非必須的,可以不填。
再看藍色框框,請假事由必須填,照片可以不填。
外出事由是必須填的,沒事別亂跑,好好上班。
加班事由可以不填,叫你加班還需要理由么?
分析過后,我們總結(jié)一下,紅色框里的是相同的功能可以提出來復用,而藍色框是每個功能獨有的。
我們看看用抽象類的高端玩家和不用抽象類的普通玩家是如何設(shè)計以上功能。

普通玩家設(shè)計了三個功能,自己體會。

高端玩家抽象了一個抽象父類,這樣設(shè)計還有一個優(yōu)點。如果像普通玩家一樣設(shè)計三個獨立的類,那么可能會漏掉功能,比如說在請假單里面,忘記寫add_reason這個方法,這是有可能發(fā)生的。
而如果設(shè)計成子類繼承抽象父類,則不會發(fā)生這種情況,因為抽象方法必須實現(xiàn),不然就報錯。這也是用抽象類來規(guī)范子類的一個好方法。
請好好理解本章內(nèi)容,因為下一章,會介紹一個比抽象類更抽象的一個知識點,請做好準備。