大多數(shù)人所謂的 OOP,其實都是說的“繼承封裝多態(tài)”這一套,但是,最早的 OOP,叫對象范式,對象范式的兩個基本觀念:
*.程序是由對象組成的;
*.對象之間互相發(fā)送消息,協(xié)作完成任務
請問,有“繼承封裝多態(tài)”的定義嗎?沒有?。?!這兩個觀念與后來我們熟知的面向?qū)ο笕亍胺庋b、繼承、多態(tài)”根本不在一個層面上。倒是與再后來的“組件、接口”神合。
世界上第一個面向?qū)ο笳Z言是 Simula-67,第二個面向?qū)ο笳Z言是 Smalltalk-71。Smalltalk 受到了 Simula-67 的啟發(fā),基本出發(fā)點相同,但也有重大的不同。先說相同之處,Simula 和 Smalltalk 都秉承上述對象范式的兩個基本觀念,為了方便對象的構造,也都引入了類、繼承等概念。也就是說,類、繼承這些機制是為了實現(xiàn)對象范式原則而構造出來的第二位的、工具性的機制。而 Simula 和 Smalltalk 最重大的不同,就是 Simula 用方法調(diào)用的方式向?qū)ο蟀l(fā)送消息,而 Smalltalk 構造了更靈活和更純粹的消息發(fā)送機制。
到了 1980 年代,C++出現(xiàn)了。Bjarne Stroustrup 在博士期間深入研究過 Simula,非常欣賞其思想,于是就在 C 語言語法的基礎之上,幾乎把 Simula 的思想照搬過來,形成了最初的 C++。C++問世以之初,主要用于解決規(guī)模稍大的傳統(tǒng)類型的編程問題,迅速取得了巨大的成功,也證明了對象范式本身所具有的威力。
大約在同期,Brad Cox 根據(jù) Smalltalk 的思想設計了 Objective-C,可是由于其語法怪異,沒有流行起來。只有 Steve Jobs 這種具有禪宗美學鑒賞力的世外高人,把它奉為瑰寶,與 1988 年連鍋把 Objective-C 的團隊和產(chǎn)品一口氣買了下來
形勢使然,C++的廣泛使用,大大的影響了學術界,學術界瘋狂的熱愛繼承這套體系,希望利用繼承來描述世間的真實類別系統(tǒng),然而現(xiàn)實世界復雜多了,蝙蝠是鳥也是獸,水上飛機能飛也能游,它們該如何歸類呢。這套繼承體制遇到真實世界的時候破綻很大,但是學界已經(jīng)剎不住車了,甚至搞出了多重繼承。這股風潮影響了后續(xù)的 Java (雖然它沒“繼承”那套翔一樣的多繼承機制,引入了接口這個其實更接近 OOP 本質(zhì)的東西),扭曲了人們對面向?qū)ο蟮睦斫?。既然必須要先知道對象的類型,才能向?qū)ο蟀l(fā)消息,那么“類”這個概念就特別重要了,而對象只不過是類這個模子里造出來的東西,反而不重要。漸漸的,“面向?qū)ο缶幊獭弊兂闪恕懊嫦蝾惥幊獭?,“面向類編程”變成了“構造類繼承樹”。放在眼前的鮮活的對象活動不重要了,反而是其背后的靜態(tài)類型系統(tǒng)成為關鍵?!胺庋b、繼承”這些第二等的特性,喧賓奪主,儼然成了面向?qū)ο蟮囊?。每個程序員似乎都要先成為領域?qū)<?,然后成為領域分類學專家,然后構造一個完整的繼承樹,然后才能 new 出對象,讓程序跑起來。
到了 1990 年代中期,問題已經(jīng)十分明顯。UML 中有一個對象活動圖,其描述的就是運行時對象之間相互傳遞消息的模型。1994 年 Robert C. Martin 在《 Object-Oriented C++ Design Using Booch Method 》中,曾建議面向?qū)ο笤O計從對象活動圖入手,而不是從類圖入手。而 1995 年出版的經(jīng)典作品《 Design Patterns 》中,建議優(yōu)先考慮組合而不是繼承,這也是盡人皆知的事情。這些跡象表明,在那個時候,面向?qū)ο笊鐓^(qū)里的思想領袖們,已經(jīng)意識到“面向類的設計”并不好用。只可惜他們的革命精神還不夠,delphi 之父在創(chuàng)建.net 的時候,曾經(jīng)不想要繼承,在微軟內(nèi)部引起了很大的爭議,最后是向市場低頭,加上了繼承。
2000 年后,工程界明確的提出:“組合比繼承重要,而且更靈活”,Go 語言也許是第一個明確的對這種思路進行回應的語言,你認為 Go 不夠 OOP,那是因為你觀點里的 OOP 其實是被扭曲過的,時至今日,學術界仍然很關注繼承,但是工程界的思路已經(jīng)變了,OOP 本質(zhì)是為了職責分離而設計的范式,核心的東西是對象,不一定需要類,OOP 也不是繼承封裝多態(tài)的代名詞