面試的時候,面試官問,你是怎麼理解物件導向的程式設計?我想很多人會照著面試題來背吧,物件導向呀,不就是繼承,封裝,多型嗎?注意,面試官問到這裡,是想聽聽你對物件導向的理解,而不是讓你來背概念。
物件導向,是對現實世界的模擬,下圖我們簡單模擬了一個動物世界。
物件導向的三個基本特徵之一繼承,這裡Primat繼承了Animal,Person繼承了Primat,繼承很簡單,就不多說了,看以下程式碼實現,程式碼中的註釋比較重要,請重點看。
在程式碼中,不管是動物,鳥類,人類,猴子,我們都可以抽象成類,類是物件的模板,通過new關鍵字,可以建立一個個物件。仔細看藍色框裡的內容,animal1和animal2,雖然都是同一個形態(Animal),由於指向的是子類物件,當呼叫同一個eat()方法,執行時會智慧匹配到子類的實現,最後得到的結果也不一樣,這種形為,我們稱之為多型。
多型要滿足三個條件。
一、要有繼承;(Person繼承了Animal,Monkey也繼承了Animal)
二、要有重寫;(都重寫了父類的eat方法)
三、父類引用指向子類物件。(紅框內容)
再看下圖,利用IDE的程式碼聯想功能看一下,person4這個物件能訪問到name、sex屬性,eat()、printAge()方法,但無法訪問age屬性,isLady()方法。是因為我們在該屬性和方法前面加了private關鍵字。隱藏了不想對客戶端暴露的age屬性和isLady()方法(這裡的客戶端是main方法),但是我們對客戶端提供了一個printAge方法來列印年齡,但在列印年齡前,我們對年齡做了一系列處理(不列印女士年齡)。
對於這種隱藏物件屬性和實現細節,僅對外公開指定方法來控制程式中屬性的訪問和修改,我們稱之為封裝。(這兒我們沒有對age提供set方法,壓根沒法修改,提供了一個printAge()方法供外部訪問)。
在工作中,我們可能會有這麼一個需求,當Person物件的名字一致,年齡一致,性別一致,就當成同一人處理。如果之前看過我 說說Java裡的equals(上) - 知乎專欄 一文的人,大家應該不會用==或equals直接去做比較,以下是結果。
當用==和equals失敗後,開發者可能會寫下以下程式碼去做判斷
寫到年齡邏輯的時候發現,由於age屬性是私有的,又沒有提供getAge( )方法,獲取不到age屬性,可能會在Person這個類裡提供一個getAge( )方法或把age的private關鍵字去掉,這樣雖然也能完成邏輯,但會導致後續使用該類的人再也不調printAge去列印age了,而是直接訪問age屬性或getAge( )方法去列印,女士的age也就暴露了出去。很顯然,這種做法打破了我們之前對age的封裝,不建議這麼做。
age是私有的,那我們把這段程式碼挪到Person物件裡不就行了?好主意,比較兩個物件是否相等,不應該由客戶端來決定,而是由物件本身來決定。這也是物件導向的技巧之一。
有了以上思路,我們在Person裡擴充套件了一個方法,
一切似乎很完美,結果也和我們期望的一樣,問題似乎解決了。
我們知道Set裡的元素無放入順序,元素不可重複,請思考以下程式碼的執行結果:
希望看完本章後,讀者對物件導向有了自己的一些看法和思考,而不是面試題中一味出現的六個字,多型,繼承,封裝。甚至你可以對面試官莞爾一笑,啊,我還沒物件,有大把的時間投入到工作中來。
評論區裡,有人說Animal,Primat應該宣告為抽象類而不是介面,其實兩種方式都是可以的。如果Animal暫時不確定有屬性或有具體的形為,建議先宣告成介面,因為一個類可以實現多個介面,但只能繼承一個類,宣告為介面更靈活一些,也使實現類具有更好的擴充套件性。
注:本專欄文章首發於公眾號:saysayJava。所有示例程式碼均已上傳至公眾號,需要請關注下載。
如果喜歡本系列文章,請為我點贊或順手分享,您的支援是我繼續下去的動力,您也可以在評論區留言想了解的內容,有機會本專欄會做講解,最後別忘了關注一下我。
轉載無限歡迎,但請註明「作者」和「原文地址」。轉載請在文中保留此段,感謝您對作者版權的尊重。如需商業轉載或刊登,請聯絡作者獲得授權。
下一篇:說說Java裡的equals(中)- Java那些事兒