理解面向?qū)ο?/h2>

理解面向?qū)ο?/h1>

閱讀知乎大牛對面向?qū)ο蟮挠懻摵?,寫下自己的總結(jié)和理解。知乎

面向?qū)ο蟮脑咎匦?/h2>

面向?qū)ο笤镜奶匦裕ê锰帲┦鞘裁茨兀吭谖覀兊恼n本中赫然的寫著三個特性:封裝、繼承、多態(tài)。然而,對于我們代碼量少得可憐的初學者來說,怎么都不會理解這些概念。再加上老師和課本上都說面向?qū)ο笫嵌嗝春玫木幊谭妒剑瑢е挛覀冇绣e誤的理解——編程就應該用面向?qū)ο?,面向?qū)ο竽軐懗龊玫某绦颉_@種理解就會讓我們到處使用面向?qū)ο?,看到一個問題就立馬先來一個class再說,看到成員變量就放在private里邊,認為這體現(xiàn)了封裝,等到寫算法的時候私有變量又礙手礙腳,又不得不移出來(或者寫一些getter和setter方法到處打洞),看到teacher、student、worker就一定會寫一個person類繼承之,本來簡單的問題最后搞出來好多類,然后類之間各種存在關(guān)系,最后還不一定能解決問題,所以搞得我初學面向?qū)ο蟮臅r候懷疑面向?qū)ο笫遣皇怯袉栴}啊。我相信很多像我一樣的普通學生都會有這樣的體會。
面向?qū)ο螽斎徊皇菦]用的。面向?qū)ο笫乔拜叴笈兛偨Y(jié)出來的成功經(jīng)驗,只不過是我們沒用對。首先,我們要知道面向?qū)ο笾皇潜姸嗑幊谭妒街械囊环N,所以它有最適合使用它的場景,并不是所有問題都能高效率的解決,每種范式都有自己適合使用的場景,絕不能認為面向?qū)ο髮懗鰜淼囊欢ㄊ亲詈玫?。因此,我們要結(jié)合實際問題,必須經(jīng)過充分地分析,選擇最合適的范式。當然這個選擇肯定是有經(jīng)驗的程序員來做的。面向?qū)ο蟛皇侨f能的,它不能解決所有問題

關(guān)于這一點,知乎中大牛用WOW中英雄眾多的技能設(shè)計問題,說明的非常好,如果用面向?qū)ο髞碜?,類的?shù)量可能會爆炸,而通過表格驅(qū)動的思想代碼量會減少很多,并且可擴展性也更強

對于那23中設(shè)計模式的學習和使用也是存在類似的問題,如果使用了不合適的設(shè)計模式,會發(fā)現(xiàn)可能問題是被解決了,但是類咋這么多呢,是不是太啰嗦了呢?當然,你可能會說類多啰嗦,是因為考慮到了擴展性,以后寫代碼就方便了。大多數(shù)情況并非如你所愿,可能那堆代碼后來就根本沒有擴展過,可擴展性是個偽需求,也可能真正有需求變更時,之前啰嗦的設(shè)計使得擴展更加困難。一切源于我們對需求對問題認識的不清楚,就往某個設(shè)計模式里生搬硬套。

面向?qū)ο蟮奶匦云鋵嵵挥袃蓚€:封裝與接口歸一化。

封裝

封裝絕對不是將變量不加思索的放在private里邊。封裝的意義在于區(qū)分內(nèi)和外,通過接口向程序的調(diào)用者表明哪些操作是允許的哪些是不允許的(怎么表達不允許呢?例如我們不希望從外部構(gòu)建對象,就需要將構(gòu)造函數(shù)隱藏)。好的封裝應該是使用者的任何需求都能無阻礙的滿足而不是受限于各種私有變量,并且內(nèi)部實現(xiàn)不管怎么改變都不會影響外部的程序。所以封裝是個很復雜的設(shè)計過程,必須經(jīng)過充分地思考才有可能設(shè)計出好的接口。好的封裝應該是透明的,使用者不會察覺到它的存在。

接口歸一化

接口歸一化=接口繼承+多態(tài)。
這里為什么要將繼承和多態(tài)并列呢?因為不實現(xiàn)多態(tài)的繼承是沒有意義的,或者說使得面向?qū)ο笤镜奶匦該p失一大半了。我們知道繼承分為接口繼承實現(xiàn)繼承,實現(xiàn)繼承我們經(jīng)常說能夠讓代碼重用,能夠支持開閉原則,然而現(xiàn)在普遍的結(jié)論是實現(xiàn)繼承使得類結(jié)構(gòu)變得復雜,類設(shè)計開銷增大,如果代碼我們可以自由修改,繼承往往不是最佳選擇。
接口繼承和多態(tài)是相輔相成的,他們一起實現(xiàn)了接口歸一化。接口歸一化的典型案例就是:

  • Linux的泛文件概念,硬盤、USB、鍵盤、 網(wǎng)絡(luò)等所有東西都被抽象為文件。
  • UI框架中,所有對象都是window,都可以響應窗口事件。
  • 游戲編程中,所有對象都是可以感受到時間的精靈。

可以看出來,接口歸一化就是將所有擁有相同操作的對象統(tǒng)一到一起,調(diào)用者無需關(guān)心每個對象的具體細節(jié),統(tǒng)一的接口使得調(diào)用者無差別地對待這些對象,使得開發(fā)變得方便。這個特性就是面向?qū)ο笞畲蟮奶匦?。所以在你遇到的問題中需要這種歸一化無差別地操作時,選擇面向?qū)ο髴摬粫e。

面向?qū)ο笾械恼`區(qū)

一切皆對象

這句話在面向?qū)ο缶幊讨袘摲浅3R?,這句話的禍害在于鼓勵了大家不假思索地多寫類,慫恿了大家勇敢使用面向?qū)ο?。其實根?jù)上面的討論,我們應該將那些具有統(tǒng)一操作的對象統(tǒng)一到一起,也就是說一切對象都可以做XX才是正確的論述,并且這個對象可以做什么,是我們結(jié)合具體的問題抽象出來的結(jié)果,可能和實際生活中的分類重疊,也可能完全不同。我們不能憑生活經(jīng)驗或者常識進行分類,比如:所有正方形都是矩形,如果正方形從矩形繼承,那什么是正方形的長寬?我們修改了正方形的長,那它還是正方形么?所以在抽象類別時,需要結(jié)合實際問題。

只有面向?qū)ο笳Z言才能實現(xiàn)面向?qū)ο?/h3>

Linux不是用面向?qū)ο笳Z言寫的但它的泛文件設(shè)計依然體現(xiàn)了面向?qū)ο蟮乃枷?。面向?qū)ο笳Z言只是在語言層面提供便利,讓我們更快更簡單的實現(xiàn)面向?qū)ο笏枷搿?/p>

面向?qū)ο笫菬o害的

同前邊討論設(shè)計模式一樣,如果在不合適的場景(比如那個WOW的例子或者如此面向?qū)ο?/a>中的討論)使用面向?qū)ο?,那面向?qū)ο笾荒苁怯泻Φ?。還有不要以為面向?qū)ο缶褪潜让嫦蜻^程牛逼,各種編程范式?jīng)]有誰優(yōu)誰劣只有合不合適。面向?qū)ο蟛皇蔷幊痰奈ㄒ贿x擇。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容