發(fā)現(xiàn)神作一枚,淺顯易懂解釋了面向?qū)ο缶幊痰陌l(fā)展歷史,轉(zhuǎn)載分享
源 | 碼農(nóng)翻身 文 | 老劉
-第一天-
上帝看到人類發(fā)明了計(jì)算機(jī),但一直在用匯編語(yǔ)言艱難地寫程序,很是傷心,就把編譯器的秘密告訴了約翰·巴科斯,讓他帶領(lǐng)大家寫出了編譯器,從此人類可以用高級(jí)語(yǔ)言寫程序,然后編譯成機(jī)器語(yǔ)言去運(yùn)行了。
上帝還教會(huì)了人類使用順序、循環(huán)、分支這三種基本的程序結(jié)構(gòu)來(lái)編寫程序。
人類很高興,寫的代碼越來(lái)越長(zhǎng)。
-第二天-
但是人類經(jīng)常寫下臭長(zhǎng)臭長(zhǎng)的代碼,然后把代碼Copy得到處都是。
上帝說(shuō):“要有函數(shù)!你們可以用函數(shù)把長(zhǎng)長(zhǎng)的代碼封裝起來(lái),這樣就寫一次,就可以到處調(diào)用了?!?/p>

人類又發(fā)現(xiàn)有些函數(shù)的參數(shù)太長(zhǎng), 記不住,調(diào)用層次深的時(shí)候讓人抓狂:

上帝告訴Dennis Ritchie:“找個(gè)數(shù)據(jù)結(jié)構(gòu)把參數(shù)組織起來(lái),以后就傳遞這個(gè)數(shù)據(jù)結(jié)構(gòu)!”

上帝教導(dǎo)人類:程序 = 數(shù)據(jù)結(jié)構(gòu)+算法
人類看到清爽的代碼,覺(jué)得很舒服。
-第三天-
有人寫了一個(gè)程序,用一個(gè)數(shù)據(jù)結(jié)構(gòu)和函數(shù)實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的棧。

上帝看到了,皺了皺眉頭,說(shuō)道:“這個(gè)數(shù)據(jù)結(jié)構(gòu)對(duì)外完全是不設(shè)防啊,不但自己的算法push,pop,top等可以操作,使用這個(gè)Stack的客戶也可以操作elements這樣的內(nèi)部數(shù)據(jù)結(jié)構(gòu),可以獲取任意元素的值,而不僅僅是通過(guò)push,pop來(lái)操作。依照人類的本性,還不搞得天下大亂? 不好不好?!?/p>
上帝說(shuō):“要有Object?。?!”
上帝把Alan Kay叫來(lái),告訴他:要把數(shù)據(jù)和操作給結(jié)合起來(lái),形成Object,以后Object的屬性數(shù)據(jù)不允許直接訪問(wèn),只能通過(guò)這個(gè)Object的函數(shù)來(lái)操作。
人類覺(jué)得Object大法好,創(chuàng)建了很多Object出來(lái),讓他們互相調(diào)用。
-第四天-
上帝發(fā)現(xiàn)很多Object的方法都是相同的,他們被重復(fù)地放在一個(gè)個(gè)對(duì)象當(dāng)中,太浪費(fèi)了。

上帝說(shuō):“要有Class!把這些重復(fù)的方法代碼從對(duì)象中剝離出來(lái),放到一個(gè)公共的Class中! ”

人類問(wèn):“那我們?cè)趺窗堰@些Object給創(chuàng)建起來(lái)?并且讓Object 和 Class關(guān)聯(lián)?”
上帝說(shuō):“可以用new 這個(gè)關(guān)鍵字: Stack object1 = new Stack(); ”
Stack類的函數(shù)定義只有一份,但是Stack類生成的Object有很多份。
人類在寫push()函數(shù),pop()函數(shù)的時(shí)候,要操作Object的數(shù)據(jù), 到底操作的是哪一個(gè)Object?
上帝說(shuō):“ 要有this !”
每次調(diào)用函數(shù)的時(shí)候,可以把要操作的Object作為一個(gè)隱藏的參數(shù)傳遞進(jìn)去。例如void push(int data),真正在調(diào)用的時(shí)候是這樣的:void push(Stack this, int data)
有個(gè)叫Guido的說(shuō):“我能不能把this改成 self ? ”
上帝說(shuō):“隨你嘍!”
還有人說(shuō):“這不又回到我們?cè)嫉臓顟B(tài)去了嗎?void push(Stack *s,int data)“
上帝告誡說(shuō):“雖然本質(zhì)相同,但是表達(dá)形式不同,之前你在語(yǔ)法層面必須傳遞一個(gè)Stack 對(duì)象到函數(shù),現(xiàn)在在語(yǔ)法層面不用加了。我會(huì)在編譯后的代碼,或者運(yùn)行時(shí)自動(dòng)給你們加上。”
Guido說(shuō):“我還是喜歡把self加到方法上!”
上帝沒(méi)有說(shuō)話,應(yīng)該是默認(rèn)了。
-第五天-
人類創(chuàng)建了很多很多的Class,上帝發(fā)現(xiàn)有些Class包含了類似的功能,還是有重復(fù)代碼。
上帝說(shuō):“要有繼承!把那些類似的、重復(fù)代碼放到父類當(dāng)中去,這樣子類就可以直接使用,不用重新再寫一遍了。”

上帝又說(shuō):“要有多態(tài)!就是對(duì)同一個(gè)接口,使用不同的實(shí)例而執(zhí)行不同操作?!?/p>
Person p = new Employee();
p.funcB() // 執(zhí)行Employee類的funcB()方法,而不是Person類的funcB()方法
人類看到繼承的好處,開始瘋狂使用。
支持單繼承和支持多繼承的兩派人還發(fā)起了多次戰(zhàn)爭(zhēng)。
上帝非常擔(dān)心,他告誡人類:“繼承其實(shí)是破壞了封裝性,父類的很多細(xì)節(jié)對(duì)子類都是可見的,父類的變化可能會(huì)極大地影響子類。”
人類不知道怎么辦。
“你們要記住一條:優(yōu)先使用組合而不是繼承?!?看到人類并不太懂,上帝叫來(lái)了Freeman , 告訴他一個(gè)“鴨子游戲”的例子,后來(lái)Freeman把這個(gè)例子寫到了一本書里,這本書叫做《Head First 設(shè)計(jì)模式》。
“還有一條,” 上帝補(bǔ)充到,“面向接口編程,而不是實(shí)現(xiàn)編程。”
人類還是不懂,上帝叫來(lái)了Eric Gamma ,告訴他在面向?qū)ο笤O(shè)計(jì)和編程中要注意的23種通用模式, 讓他和另外三個(gè)人寫了一本書《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》,但是大家都說(shuō)看不懂。
-第六天-
人類使用了繼承和多態(tài),理解了設(shè)計(jì)模式,但是代碼還是一團(tuán)糟。
上帝說(shuō):“編程的關(guān)鍵是要抽象啊!你們得把系統(tǒng)需求抽象成高層的概念,然后在概念層次進(jìn)行編程?!?/p>
這句話本身就很抽象。
有大牛學(xué)會(huì)了,寫出了很多優(yōu)秀的軟件。
大部分人表示學(xué)不會(huì)。
上帝也沒(méi)有辦法, 只是有點(diǎn)后悔,教了人類太多的東西, 而人類又不能完全掌握。
上帝一直在思考,要不還是讓人類回到機(jī)器語(yǔ)言編程時(shí)代?
或者創(chuàng)造一種 智能的機(jī)器 來(lái)替代人類編程?
-第七天-
上帝覺(jué)得累壞了,就休息了,程序員們也休息了一天。
這就是星期天的來(lái)歷。
出場(chǎng)人物:
約翰·巴科斯 : 計(jì)算機(jī)科學(xué)先驅(qū)之一、FORTRAN之父、1977年圖靈獎(jiǎng)得主、BNF(巴克斯-諾爾范式)的發(fā)明者之一。
Dennis Ritchie: C語(yǔ)言之父,Unix的創(chuàng)造者之一。
Guido van Rossum:Python之父。
Eric Freeman:《Head First 設(shè)計(jì)模式》作者之一。
Eric Gamma:《設(shè)計(jì)模式》作者之一,主要作品:JUnit,Eclipse JDT,Jazz, Visual Studio Code。
-END-