工作也有一年了,還沒讀過聖經這不是惹人笑嗎,上周終於把這本書買回來了,這兩天才開始看,一邊看呢一遍記一下筆記,用了一些自認為幽默的話來寫的,一方面自己寫的也是津津有味,另外呢也希望能夠給讀者帶來會心一笑的感覺,文中所述僅僅是本人拙見,如有不正確的地方歡迎大家指正,樓主會認真修改的。下面開始:
1.抽象過程
書中開篇就寫到每種編程語言都提供抽象機制,接下來就介紹了兩種抽象的機制,但是我沒接觸過裡面的語言所以也不再贅述,面向對象語言的抽象機制就是抽象出對象,那麼什麼是對象?對象可以看做是一台計算機,有自己的狀態,還有自己的操作,用戶可以要求對象執行這些操作。例如我桌子上的可樂瓶子,容量是600ML,容量就是這個瓶子的屬性也就是狀態,可以裝可樂就是它的方法也就是操作,可樂瓶子可以執行裝可樂的操作,當然需要發送消息,也就是調用方法。
面向對象語言的五個基本特性:
萬事萬物皆為對象
書中的說法是對象可以看做是一種奇特的能量,可以存儲數據,同時也可以要求他在自身上執行操作。我的理解是這樣的一件事情或者是一個事物,擁有自己的屬性,並且具有一些行為,那麼就可以稱之為對象,
可樂瓶子有容量,可以裝可樂,那麼它就是一個對象(原諒一個喜歡喝可樂的人的思維),顯示屏有大小,可以顯示圖形圖像,那麼它也是一個對象,一個原子,有自己的原子核,可以組成分子,那麼原子也是一個對象。。。。。。
程序是對象的集合,他們通過發送消息告訴彼此所要做的
所謂的消息也就是對某個對象的某個方法的調用請求,如果把你打電話簡單看成一個程序,那麼你和電話就是這個程序中的兩個對象,你要打電話就要告訴電話說我要打電話,但是電話不是人也不是神,他聽不懂你說的話,那麼你需要做的就是在鍵盤上按下電話號碼然後按下呼叫鍵,也就是說此時你作為一個對象調用了電話這個對象的打電話的方法,說得簡單一點就是程序是需要程序中所包含的對象根據需要互相調用彼此所擁有的方法來執行的。
每個對象都有自己的由其他對象所構成的存儲
其實這條我不是太理解,按照書中的說法是可以創建現有對象包的形式來創建新的對象,這是可以理解的,就像一個人是對象,一群人也可以看做一個對象,但是我不理解的是什麼呢?但是假如這個對象是一個人,這個人有身高有體重,可以走路可以說話,但是怎麼包含由其他對象所構成的存儲呢?是不是可以這樣理解呢?這個人要穿衣服,衣服也可以看做是一個對象,那麼這個人對象就包含了由衣服對象所構成的存儲呢?還請大神們解惑。
每個對象都有其類型
這也是必然的,一個老人是一個人,一個孩子也是一個人,他們的類型都是人,但是你能說一條美人魚是人嗎?不能,你只能說美人魚是一條魚,因為它的類型就是魚。
某一個特定類型的所有對象都可以接收同樣的消息
這個很好理解,就是只要這個對象的類型是人,不管是男人女人亦或者老人孩子,只要是人,都可以走路都可以說話(當然我說的是一般情況,如果你非要較真的說這人沒腿或者這人是啞巴,那我也沒辦法),也就是說這些類型是人的對象都可以調用走路說話的方法。
Booch對對象提出的描述是:對象具有狀態、行為和標識。對象的狀態是什麼呢?就是對象自身的屬性,例如可樂瓶子的容量,行為是對象所擁有的方法,書中對標識的定義是每一個對象在內存中都有一個唯一的地址,但是我認為標識是用來區分對象的,但是並不需要僅僅從存儲地址上來區分,可以先從對象的類型上來區分,一個孩子對象肯定不能和一個可樂對象相同吧,但是如果是一個孩子對象和一個老人對象就不能僅僅從類型上區分了,因為這兩者的類型都是人,這時候就需要從存儲地址上來區分了。
文中在講解對象的接口之前首先給出了類的定義,什麼是類呢?類也即類型或者數據類型,是具有相同特性和行為的對象的集合,或者反過來說每個對象都是唯一的,但是同時也是具有相同特性和行為的對象所歸屬的類的一部分,用關鍵字class來表示類。創建類以後,就可以根據這個類創建無數個基於此類的對象,就像你創建了一個可樂類,那麼你可以創建百事可樂對象、可口可樂對象(原諒我想不出來還有別的可樂),然後你就可以去操作你所創建的可樂對象,但是如何才能獲得有用的對象呢?或者說是怎麼讓可樂對象只裝可樂而不去裝爽歪歪呢?也就是需要某個對象只滿足某些請求,這些請求是由對象的接口來定義的,決定接口的就是我們所定義的類或者說是類型。什麼意思呢?還是可樂的例子:現在我們定義了一個可樂類叫KeLe,類中有一個方法叫zhuang(),然後KeLe baishi = new KeLe() baishi.zhuang(),我們使用new創建了baishi對象,這個對象可以去調用zhuang方法,但是我們要明白一點,這個zhuang()方法能用來裝白開水嗎?能用來裝哇哈哈嗎?不能,只能用來裝可樂,為什麼?因為baishi對象是基於KeLe類創建的,這個類是可樂類,所以他的方法也只能是裝可樂而不是別的,這進一步說明了書中所說的接口是由類型決定的。另外書中說道了接口確定了某一特定對象所能發出的請求,這個也好理解,就像上面說的你能用baishi對象去發出裝水的請求嗎?或者你能用張三的電話號碼去打通李四的電話嗎?也就是說接口用來限制對象能夠做什麼事情,這和類以及類中的方法息息相關。
關於這點的理解,這個還是以可樂為例子,可樂是拿來干嘛的?這不是廢話嗎,可樂是拿來喝的,但是可樂為什麼喝了那麼刺激那麼爽?那就要關心可樂的配料了,什麼糖啊水啊染色劑啊等等,正是這些配料一起成就了可樂,這和程序是一樣的,程序是拿來為用戶服務的,但是它需要調用其他對象的服務才能實現這一母的,就像正確的配料才能配出來可樂一樣,合適的對象才能成就完美的程序,因此作為編程人員的你就需要去創建或者說去尋找這些合適或者說是能提供理想服務來解決問題的一系列對象,將你需要解決的問題或者說編寫的程序分解成一系列對象的組合。同時書中還說道把對象看做服務提供者的一些好處,什麼好處呢?提高對象的內聚性,高內聚是軟件設計的基本質量要求之一:這意味著一個軟件構件各方面組合的很好。這個怎麼理解呢?還是可樂,大家都知道糖是提供可樂中的甜味的,水是稀釋糖讓可樂保持液體的(以上純屬虛構,如有雷同,去找可口可樂公司),但是現在如果說我不加水了,我就熬個糖稀加進去,這可樂是不是喝的更夠味啊?我想說,哥啊,那還能喝嗎?這例子什麼意思呢?意思就是說每種東西完成一個任務就行了,別做的太多,做多了人家未必領你的情,你是糖就安安靜靜的提供你的甜味,去搞什麼稀釋?那是人水的職責。對於編程一樣,一個對象提供單一的職責就夠了,不需要去負擔更多的職責,不然小肩膀扛不住不說還攪壞了一鍋粥,對誰都沒好處,這也就是我們常說的單一職責問題,如果你的對象提供了有用的服務並且按照單一職責設計,那麼在別人試圖理解你的代碼或者說復用你的代碼時都會變得更加簡單容易。
書中將開發人員按照角色分成了兩種,一種是新的數據類型的創建者稱之為類創建者,一種是使用數據類型的類消費者稱之為客戶端程序猿,那被隱藏的具體實現是什麼意思呢?意思就是類創建者創建了一個新的類,但是只是給客戶端程序員提供了接口並沒有告訴客戶端程序員我這個類的具體實現,這也是我們經常提到的面向接口編程,就是我只告訴你我這個類可以做什麼,但是怎麼做我不告訴你?就像我現在發明了一種新型的可樂,我就告訴你有糖有水就可以生產純天然綠色無公害的可樂,但是水是不是要加熱,糖是不是要冰鎮我就是不告訴你,你管我怎麼做?反正你提供水和糖我給你可樂就是了,管那麼多干嘛?編程也是如此,我就提供一個接口,你只要提供接口所需要的參數,我的接口就會給你返回你需要的數據,至於怎麼實現的跟你沒關系啊。
這麼做有什麼好處呢?其一,避免客戶端程序猿修改本不該修改的地方,我的算法就是這樣,只有這麼算才能得到結果,如果可以讓別人修改我的實現,得到了不一樣的結果,這鍋誰來背?反正我是不背,把需要隱藏的部分或者說是實現中比較脆弱的部分隱藏起來,不讓調用的人隨便改,那麼就不會出現這種情況了。其二,你對隱藏部分的修改不會影響調用者,如果你提供的不是接口而是實現類給調用者,人家也沒改你的實現方式,正常的調用,而且你這類還比較重要,人家一下用了幾千個地方,你回頭一看,不對啊,這個地方我得改改,得,你是改爽了,等調用的人測試程序的時候瞬間爆炸完成千殺,你說調用的人會不會提著刀正在趕往你家?如果你將接口和實現分開,你的實現如何改對人家調用的人都沒有影響,人家也不會沒事拿刀看你是吧?
關於修飾符范圍的問題我就不在這多說了,大家也都知道的,本來廢話就多了,再說廢話就更多了。
代碼復用相信大家都知道,比如我們通常會在工具類中寫一個日期轉換方法,使用的時候直接調用這個方法即可,當然這是方法的復用,書中所說的復用是類的復用,什麼是類的復用呢?還拿可樂說是,現在有兩家飯都賣可樂,一家賣百事可樂,一家賣可口可樂,這時候如果讓你創建類,你是創建一個可樂類好呢還是為這兩種可樂分別創建一個類呢?這不是廢話嗎,以我編程多年的經驗怎麼不知道是創建一個可樂類,再分別創建百事可樂對象以及可口可樂對象就可以了,對,這就是最簡單的類的復用方式-直接使用類的一個對象,也就是說使用類的對象來達到復用類的目的,此為其一。
那麼第二點是什麼呢?還是先說可樂,其中一家老板覺得單賣可樂不掙錢啊,怎麼辦啊?改賣套餐了,套餐有啥?鮮香雞腿、精品小菜外加可樂一(小)杯,這時候怎麼搞?你要新建一個套餐類,類裡面屬性是雞腿的大小,雞腿的顏色,可樂的大小,可樂的種類。。。。。。來個大雜燴嗎?你這個大雜燴的類管的事情是不是太多了,不符合我們所說的單一職責原則啊,怎麼辦?涼拌,這時候就需要用到復用的第二種方式--將類的某個對象置於某個新的類中,這時候你可以先創建一個可樂對象,然後只需要用套餐類包含可樂對象就可以了,我管你是百事還是可口的我只需要知道我裡面需要有個可樂就行了,至於可樂的屬性那就交給可樂類去維護就行了,我不需要知道,同樣其他的雞腿啊小菜啊都是如此,這樣做的結果是套餐類只需要知道我裡面有什麼,至於各自的屬性讓各自的類去維護好了,這樣是不是就不違背單一職責原則了呢?
由任意數量的任意對象以任意可以實現新的類中想要的功能的方式組成新類的方式稱之為組合,如果組合是動態發生的,那麼也稱之為聚合(關於組合和聚合的區別大家可以自行百度),組合被視為“has-a”關系,也就是擁有關系,就像人擁有手腳一樣,至於組合和繼承的關系下一節再說吧。
這會兒在地鐵上,用手機來碼字說一下繼承,書沒在身邊,但願不會說錯。首先來說一下為什麼會出現繼承?前面說到萬事萬物皆為對象,每一個對象又是某一個類的一個實例,那麼現在還是可樂的例子,我們都知道有百事可樂和可口可樂,那麼好了,我們現在可以創建兩個類,分別是百事可樂類BaiShiClass和可口可樂類KeKouClass,這兩個類裡面都有兩個屬性,分別是價格、容量,這樣沒問題吧,但是我們得知道兩個問題,第一,不管是百事可樂還是可口可樂,這兩者都是可樂;第二,現在的可樂種類只有兩種。如果現在出現了第三種第四種乃至第N中可樂,那麼是不是我們要為每一種可樂都創建一個類,並且在各自的類裡面寫上價格和容量這兩種屬性呢?大家可以想一下,這樣做是錯的嗎?不是,這樣做是無可厚非的,但是這樣做又是麻煩的,對於我們這些害怕麻煩的程序猿來說,麻煩就意味著你要加班,那麼怎麼搞?聰明的java設計者給我們搞了一個繼承(以上單純是為了引出繼承的YY,具體繼承的出現請自行度娘),繼承怎麼做呢?很簡單,創建一個KeLe類作為父類(基類),然後讓具體的可樂類去繼承我們創建的父類,繼承以後子類自動具有了父類的屬性和行為,什麼意思呢?就是說你管你老爹叫皇阿瑪,你老爹退位了,你當上皇帝了,以前管你老爹叫皇上的人現在得管你叫皇上,以前你老爹穿的龍袍現在歸你穿了,就是這個意思。只要子類繼承了父類,那麼子類就擁有父類的一切。這時候有人會有這樣的疑問,就像你說的,如果你的百事可樂繼承了可樂,同時你的可口可樂也繼承了可樂,那這兩者不是都混為一談了嗎,你這是強行合並了百事可樂公司跟可口可樂公司啊,然也非也,何以為然呢?何以為非呢?且聽我細細道來,子類繼承了父類,擁有父類的一切屬性和方法,但是子類也可以擁有自己的屬性和自己的方法,如果子類沒有自己的屬性或者方法,那麼這是最基本的繼承,子類與父類的關系是"is-a",可以簡單的說子類就是父類,你能說百事可樂不是可樂嗎?你能說可口可樂不是可樂嗎?但是如果子類在繼承父類的用時還擁有自己的屬性和方法,那麼子類和父類之間就是"is-like-a"的關系,子類像是父類,但是和父類又不完全相同,這個也很好理解,唐高祖李淵是皇帝,他的兒子唐太宗李世民也是皇帝,太宗繼承了高祖的皇位,兩者相同點是什麼呢?相同點是都是皇帝,同時不同點也很明顯啊,所以只能說兩人相似,但是你能說這是一個皇帝嗎?還有一點,子類繼承了父類的方法和屬性,但是子類對於繼承而來的方法也是有重寫的權利的,什麼意思?舉個簡單的例子,你老爹吃飯喜歡吃飯面條,但是你吃飯喜歡吃米飯,同樣是吃飯,但是你們倆吃的東西不一樣,或者說一個喜歡用鍋吃,一個喜歡用盆吃,這不也是嗎?所以說,子類可以擁有父類的方法,但是對於方法是可以重寫的,不一定要墨守成規。
今天暫時就寫到這裡了,有說的不對歡迎大家指正,樓主會繼續努力的。