周末午后,我正在愉快的打著王者榮耀,五殺在即之際。女朋友拿著一本我看過的《面向對象編程》過來找我。
什么是面向對象?是要面向我寫代碼嗎?
不是啦,這個面向對象的對象不是你這個對象啦。
此時,我突然感受到了一股莫名的殺氣。
什么?你還有其他對象嗎?有我好看嗎?有我瘦嗎?不對。你不能有其他對象。
什么是面向對象?
面向對象,英文名字叫Object Oriented,是一種軟件開發方法。是和面向過程相對應的。
別給我拽英文。給我詳細說說,說不明白今天就沒完。
我有點餓了,要不然你給我做點飯,我慢慢的詳細給你講吧。
我現在就想聽你給我講,咱們直接點外賣吧,別自己動手做飯了。
其實,對于吃飯這件事兒,就可以分為面向過程吃飯和面向對象吃飯。自己親自下廚就是面向過程,點外賣就是面向對象。
在面向過程的吃飯中,我們想要填飽肚子,需要自己親自下廚把這頓飯做出來,那么,我們就需要先想好吃什么、然后去買菜、洗菜、洗米、蒸飯、炒菜等等一系列的事情。
pubic void 做飯(){ 制定菜單(); 買菜(); 洗菜(); 洗米(); 蒸飯(); 炒菜(); }
那么,你說和點外賣相比,自己做飯有哪些缺點啊?
那還用說,麻煩唄。
的確,面向過程編程也一樣,由于想要完成做飯這件事,需要自己定義很多個方法。除此之外,還有很多遇到很多其他問題,比如:
我不想吃米飯,我想吃饅頭。
上次買的菜家里面還有,不需要去買菜。
中午吃剩下的菜家里面還有,直接熱一熱就可以吃了。
這次去的一家超市提供洗菜服務,不需要我們自己洗菜了。
以上這些突發事件,在編程中就叫做需求變更或者新的需求,這種事情發生是必然會發生的。
那么,有新的需求了怎么辦,上面這種自己動手做飯的場景,就只能重新拼湊咯。
對于程序員來說,就需要通讀代碼,找出可以復用的方法,然后重新調用,不能復用的就重新寫一個。時間久了,方法就會越來越多,系統維護越來越復雜。
面向對象,其實就是我們通過點外賣的方式來“做飯”。我們知道我們需要一頓飯,我們只需要打開外賣軟件,在里面選擇我們需要的菜品然后下單就可以了。我們不關心飯店做飯的過程。想吃什么點什么,家里來人了就再下一個訂單,不想吃米飯了,想吃饅頭了,也可以給飯店打電話,讓他們把米飯換成饅頭。
外賣軟件.點餐(紅燒肉,糖醋魚,可樂一瓶).送達時間(一小時后).備注(可樂加冰)
所以,通過面向對象的方式“做飯”,就像上面的代碼一樣。
哦,我明白了,面向對象就是把本來可能需要自己做的事情交給別人來做?對于我來說,外賣軟件就是個對象,我再面向他“做飯”,其實是他幫我做的。
額、你說的也對,也不對。在這個場景中,確實可以把外賣軟件當做是「對象」。其實,在面向對象編程中,拋棄了函數,想要實現一個功能不再是通過函數的疊加調用實現的了。而是通過對象。
對象就是對事物的一種抽象描述。現實世界中的事物,都可以用「數據」和「能力」來描述。
比如我要描述一個人,「數據」就是他的年齡、性別、身高體重,「能力」就是他能做什么工作,承擔什么樣的責任。
描述一個外賣軟件,「數據」就是他包含的菜品,而「能力」就是他可以點菜。
什么是封裝?
我們把「數據」和「能力」組合成一個對象的過程就叫做「封裝」。
封裝的結果就是可以有一個類,通過這個類我們可以獲得一個對象。然后我們就可以通過給這個對象下命令,讓他執行自己的「能力」。
除了把「數據」和「能力」封裝成一個「對象」更加方便使用以外,還有啥其他的特點么?
封裝只是面向對象的第一步,目的是把現實世界的東西抽象成對象。面向對象真正有威力的地方是「繼承」和「多態」。
舉一個不是很恰當,但是女朋友比較容易理解的例子。
我們使用外賣軟件點餐,當我們第二次去某一家店時,外賣軟件會提示你上一次你在這家點了什么,你可以點擊<再來一單>把上次的菜品直接加到購物車中,這就是「繼承」。而在購物車中的物品你可以直接付款下單,也可以把增刪和修改菜品。這就是「多態」。
什么是繼承?
在面向對象編程中,當兩個類具有相同的特征(屬性)和行為(方法)時,可以將相同的部分抽取出來放到一個類中作為父類,其它兩個類「繼承」這個父類。繼承后子類自動擁有了父類的部分屬性和方法。
通過繼承創建的新類稱為“子類”或“派生類”。
被繼承的類稱為“基類”、“父類”或“超類”。
比如:
狗{ 吠(); } 牧羊犬 繼承 狗{ 放羊(); }
上面的例子中,狗類是父類,牧羊犬類是子類。牧羊犬類通過繼承獲得狗類的吠()的能力,同時增加了自己獨有的放羊()的能力。轉換成JAVA代碼如下:
public class Dog{ public void bark(){ System.out.print("旺旺旺"); } } public class HerdingDog extends Dog{ public void herd(){ System.out.print("放羊中...."); } } public class Main(){ HerdingDog dog = new HerdingDog(); dog.bark(); dog.herd(); }
什么是多態?
同一操作,作用于不同的對象,可以產生不同的結果,這就是「多態」。通常說的多態都是指運行期的多態,也叫動態綁定。
要實現多態,需要滿足三個條件:
有類繼承或接口實現、子類重寫父類的方法、父類引用指向子類的對象。比如:
犬科動物{ 吠(); } 狗 繼承 犬科動物{ 吠(){旺旺旺} } 狼 繼承 犬科動物{ 吠(){嗷嗷嗷} }
狗和狼都是犬科動物,拉來一直犬科動物,如果它你叫的話,你可能沒辦法直接分辨出他到底是狼還是狗。只要他真正的叫出來的時候,你才知道。這就是運行時多態。轉化成Java代碼如下:
public class Canidae{ public void bark(); } public class Dog extends Canidae{ public void bark(){ System.out.print("旺旺旺...."); } } public class Wolf extends Canidae{ public void bark(){ System.out.print("嗷嗷嗷...."); } } public class Main(){ Canidae canidae = new Dog(); canidae.bark(); Canidae canidae1 = new Wolf(); canidae1.bark(); }
這樣,就實現了多態,同樣是Canidae的實例,canidae.bark調用的就是Dog類的方法,而canidae1.bark();調用的卻是Wolf的方法。
有人說,你自己定義的對象,定義的時候不就知道canidae到底是什么類的對象了么,這個其實并不決定的,很多時候我們可能不知道,原因是,對象可能并不是我們自己new出來的,比如Spring的IOC。
奧,那我終于知道什么是面向對象編程了。
嗯,對了,外賣點好了么?
呃....
(全文完)
文章來源:https://dwz.cn/gd0GXLFX
作者:漫畫編程