冒號(hào)課堂§2.3:對(duì)象范式
冒號(hào)課堂
第二課 重要范式(3)
2.3對(duì)象范式——民主制社會(huì)的編程法則
民為貴,社稷次之,君為輕 ——《孟子·盡心下》
關(guān)鍵詞:編程范式,OOP,面向?qū)ο?/span>,過(guò)程式編程
摘要: OOP簡(jiǎn)談
?提問(wèn)
- OOP是一種特殊的命令式嗎?
- OOP的基本思想是什么?
- OOP到底好在哪里?
- OOP將要一統(tǒng)天下嗎?
- 過(guò)程式編程與OOP在設(shè)計(jì)理念上有什么差異?
:講解
短憩之后,引號(hào)迫不及待地問(wèn):“面向?qū)ο蟮姆妒綉?yīng)該是一種特殊的命令式吧?”
“面向?qū)ο螅?#8221;冒號(hào)咕噥著,“姑且稱(chēng)之為OO或?qū)ο笫桨桑炔粯?biāo)新立異,也不以訛傳訛。在回答你的問(wèn)題之前,請(qǐng)先回答我的:什么是OOP?”
引號(hào)應(yīng)答如流:“OOP(Object-Oriented programming)是一種計(jì)算機(jī)編程模式,它以對(duì)象作為問(wèn)題空間的基本元素,利用對(duì)象和對(duì)象間的相互作用來(lái)設(shè)計(jì)程序。所謂對(duì)象,是實(shí)際問(wèn)題中實(shí)體的抽象,具有一定的屬性和功能。OOP的三個(gè)基本特性是:封裝性、繼承性和多態(tài)性。所謂封裝性就是——”
冒號(hào)作了個(gè)暫停的手勢(shì):“OOP的的基本特性相信大家早就耳熟能詳了,那么根據(jù)你剛才的定義,能否得出OOP一定是命令式的結(jié)論?”
引號(hào)歪頭想了一陣,答道:“從定義上好像并不能得出,難道C++、Java、C#不是命令式的嗎?”
冒號(hào)回答:“當(dāng)然是,但這不妨礙Clos成為OO版的Lisp,而Prolog也有不少融入OO特征的擴(kuò)充,如Visual Prolog、Logtalk等。OOP雖然是在命令式的基礎(chǔ)上發(fā)展起來(lái)的,但其核心思想可泛化為:以數(shù)據(jù)為中心組織邏輯,將系統(tǒng)視為相互作用的對(duì)象集合,并利用繼承與多態(tài)來(lái)增強(qiáng)重用性。這種思想也能應(yīng)用到函數(shù)式和邏輯式中,只不過(guò)對(duì)象的方法從命令式中的過(guò)程分別換成函數(shù)式中的函數(shù)和邏輯式中的斷言罷了。大致說(shuō)來(lái),命令式、函數(shù)式和邏輯式互相平行,而OOP與它們正交。”
問(wèn)號(hào)提問(wèn):“OOP已經(jīng)成為一種潮流,上堂課列舉的十二種流行語(yǔ)言中只有C不是OO的,這是否意味著OOP將要一統(tǒng)天下?”
“嚴(yán)格說(shuō)來(lái),VB(VB.NET除外)和JavaScript也不是OO的,只是基于對(duì)象的(Object Based)[1]。” 冒號(hào)糾正道,“至于OOP是否會(huì)一統(tǒng)天下,答案是否定的。首先,與能獨(dú)當(dāng)一面的三類(lèi)最基本的范式不同,純粹的OOP是不存在的[2],必須結(jié)合其他范式;其次,世上沒(méi)有包治百病的萬(wàn)靈丹方,OOP也不例外。用軟件業(yè)的行話(huà)來(lái)說(shuō):沒(méi)有銀彈(No silver bullet)[3]。OOP最適用于大型復(fù)雜的、交互式的、尤其是與現(xiàn)實(shí)世界密切相關(guān)的系統(tǒng),但在小型應(yīng)用、數(shù)學(xué)計(jì)算、符號(hào)處理等方面并無(wú)優(yōu)勢(shì)。需要指出的是,語(yǔ)言和范式的流行,與大公司支持和商業(yè)推動(dòng)是密切相關(guān)的。有人說(shuō)OOP其實(shí)是MOP(Money-Oriented Programming),即以金錢(qián)為導(dǎo)向的。雖有過(guò)激之嫌,但有經(jīng)驗(yàn)的股民都知道,有主力運(yùn)作的股票總是漲得快一些的。當(dāng)然OOP能流行,自有獨(dú)到之處,誰(shuí)能說(shuō)說(shuō)它到底好在哪里?”
逗號(hào)搶答:“OOP能提高軟件可重用性、可擴(kuò)展性和靈活性。”
冒號(hào)反問(wèn):“為什么過(guò)程式編程的可重用性、可擴(kuò)展性和靈活性就差呢?”
感到來(lái)者不善,逗號(hào)有點(diǎn)發(fā)虛:“因?yàn)?/span>OOP具有信息隱藏、繼承和多態(tài)的特征。”
冒號(hào)并不買(mǎi)帳:“首先,將可重用性、可擴(kuò)展性和靈活性與OOP劃等號(hào),是只見(jiàn)樹(shù)木,不見(jiàn)森林——那是所有范式和語(yǔ)言的共同目標(biāo)。其次,以C語(yǔ)言為例,信息隱藏可用關(guān)鍵字static來(lái)實(shí)現(xiàn);繼承可用合成( composition)來(lái)代替;多態(tài)雖然困難些,也有變通之法。更何況這些只是手段而非目的,只要設(shè)計(jì)合理,C程序同樣具有可重用性、可擴(kuò)展性和靈活性,性能效率還更優(yōu)越。即使在OOP日益風(fēng)行的今天,C的占有率始終穩(wěn)踞前列,許多大型復(fù)雜軟件如操作系統(tǒng)、數(shù)據(jù)庫(kù)等仍以C為主,這足以證明其仍堪大用。”
見(jiàn)逗號(hào)有些理屈詞窮,冒號(hào)語(yǔ)氣放緩:“請(qǐng)不要誤解,我并非OOP的反對(duì)者,相反今后還要重點(diǎn)討論它。但我希望大家少一點(diǎn)照本宣科和人云亦云,多一點(diǎn)獨(dú)立思考,甚至不妨標(biāo)新立異。”
稍作停頓,冒號(hào)繼續(xù)發(fā)問(wèn):“過(guò)程式編程與OOP在設(shè)計(jì)理念上有什么區(qū)別?”
“過(guò)程式編程的理念是重在過(guò)程,自頂向下、逐步求精[4]。”引號(hào)一出口就自感有些“照本宣科”,見(jiàn)冒號(hào)正用鼓勵(lì)的目光看著他,這才繼續(xù)說(shuō)下去,“OOP則正相反,重在數(shù)據(jù),自底向上、逐步合并。”
冒號(hào)首肯道:“如果把整個(gè)流程看作一顆倒長(zhǎng)的大樹(shù),過(guò)程式編程自樹(shù)根向下,逐漸分支,直到每片樹(shù)葉,類(lèi)似數(shù)學(xué)證明中的分析法,即執(zhí)果索因的逆推法;OOP則從每片樹(shù)葉開(kāi)始,逐漸合并,直到樹(shù)根,類(lèi)似數(shù)學(xué)證明中的綜合法,即執(zhí)因索果的正推法。”
句號(hào)心領(lǐng)神會(huì):“倘若把樹(shù)根看成主函數(shù),離樹(shù)根越近,離用戶(hù)需求也越近。如果用過(guò)程式編程,由于是逆推法,樹(shù)干改變?nèi)菀讓?dǎo)致樹(shù)枝相應(yīng)改變,因此一旦用戶(hù)需求發(fā)生變化,可能會(huì)從樹(shù)根波及到樹(shù)枝甚至樹(shù)葉,維護(hù)起來(lái)殊為不易。相反OOP從樹(shù)葉開(kāi)始設(shè)計(jì),離用戶(hù)需求較遠(yuǎn),抽象程度較高,受波及的程度較小,因此更易維護(hù)和重用。”
冒號(hào)拊掌贊道:“好極了!”
問(wèn)號(hào)不解:“您剛才不還說(shuō)C程序同樣具有可重用性嗎?”
冒號(hào)微微一笑:“數(shù)學(xué)中分析法與綜合法往往是結(jié)合起來(lái)使用的,過(guò)程式編程與OOP也是如此,只不過(guò)各有偏重罷了。句號(hào)的一番話(huà)雖不無(wú)道理,但也授OOP的反對(duì)者以口實(shí):OOP鼓吹的可重用性來(lái)自‘自底向上’的設(shè)計(jì)模式,而這種模式并非OOP的專(zhuān)利。其實(shí)軟件設(shè)計(jì)的最重要的并不是編程語(yǔ)言,甚至也不是編程范式,而是抽象思維和前瞻思維。關(guān)于這一點(diǎn),我們今后還會(huì)詳細(xì)闡述。”
嘆號(hào)不甘寂寞,插言道:“OOP以對(duì)象為基本模塊單位,而對(duì)象是現(xiàn)實(shí)中具體事物和抽象概念的模擬,這使得編程設(shè)計(jì)更自然更人性化。”
“深合吾意!”冒號(hào)揮動(dòng)著右手,“盡管OOP最大的賣(mài)點(diǎn)是其高度的可重用性,相比其他范式卻并不具明顯優(yōu)勢(shì)。但它更接近人類(lèi)的認(rèn)知模式,編程者更容易也更樂(lè)于用這種方式編程,這是它深入人心的一個(gè)重要原因。比較一下兩種用法:牛.吃(草)與吃(牛,草),哪種更接近人類(lèi)思維?”
有人在底下嘀咕:“如果把牛換成狗,那么一個(gè)是狗吃屎,一個(gè)是吃狗屎。”
全班捧腹。
冒號(hào)也忍不住笑了:“OOP人性化的另一表現(xiàn)是其接口簡(jiǎn)潔易記。看看Win32 API、Unix API等之類(lèi)操作系統(tǒng)接口或OCI之類(lèi)的數(shù)據(jù)庫(kù)接口,函數(shù)的參數(shù)動(dòng)輒七八個(gè)乃至上十個(gè),函數(shù)名和數(shù)據(jù)結(jié)構(gòu)成員也多冗長(zhǎng)晦澀,既難記又易錯(cuò)。相比之下,相應(yīng)的Java的API顯然平易近人得多。”
問(wèn)號(hào)刨根問(wèn)底:“為什么C的API不能象Java的那么簡(jiǎn)潔呢?”
冒號(hào)釋疑:“單純這么比較其實(shí)對(duì)C并不公平,因?yàn)?/span>Java的API雖然簡(jiǎn)潔易用,但功能上與相應(yīng)C的API并不等同,換句話(huà)說(shuō),Java把接口粗粒度化了。”
“接口粗粒度化?”引號(hào)質(zhì)疑道,“就是把一些函數(shù)包裝起來(lái)吧?我們也可以用C將操作系統(tǒng)、數(shù)據(jù)庫(kù)之類(lèi)的API再包裝一下。”
“事實(shí)上許多軟件公司都曾這樣做過(guò)。”冒號(hào)頷首作答,“但C函數(shù)不像Java對(duì)象,本身沒(méi)有狀態(tài),只有依靠參數(shù)傳遞或外部變量來(lái)維持相關(guān)函數(shù)之間的聯(lián)系,包裝后的接口肯定不如Java簡(jiǎn)潔,但應(yīng)該比Java高效。說(shuō)白了,OOP就是將相關(guān)的函數(shù)用數(shù)據(jù)粘合,重新包裝后再貼上對(duì)象的標(biāo)簽。從這種角度上看,與其說(shuō)OOP更具重用性,不如說(shuō)更具易用性。”
嘆號(hào)狐疑道:“OOP并不更具重用性?這可是它的金字招牌啊!”
冒號(hào)冷哼一聲:“不要被金字招牌晃暈了眼,我來(lái)問(wèn)你:是收音機(jī)、電視機(jī)之類(lèi)的電器產(chǎn)品更具重用性呢,還是與電阻、電容之類(lèi)的電器元件更具重用性?”
“當(dāng)然是電器元件啦。”嘆號(hào)沖口而出。
冒號(hào)因勢(shì)利導(dǎo):“每個(gè)電器元件具備單一的功能,正如過(guò)程式中的函數(shù);每個(gè)電器產(chǎn)品是對(duì)多個(gè)相互關(guān)聯(lián)的電器元件的封裝,正如OOP中的對(duì)象。同樣的電器元件可用于不同的電器產(chǎn)品,具有高度的可重用性,而電器產(chǎn)品重用性低,但易用性高。”
眾人猶自將信將疑。
“對(duì)一個(gè)沒(méi)有獨(dú)立思考習(xí)慣的人來(lái)講,與其說(shuō)他認(rèn)同一個(gè)理論,倒不如說(shuō)他認(rèn)同該理論倡導(dǎo)者的權(quán)威。而在他仰視權(quán)威的同時(shí),也把自己的思想交托給了權(quán)威。”冒號(hào)頗具犬儒之風(fēng),“你們可以懷疑我的觀點(diǎn),但絕不可放棄自己的思考。請(qǐng)注意,這就是我在第一堂課提到的精神——批判精神。”
冒號(hào)這時(shí)停了下來(lái),與在座的每位逐一對(duì)視。他仿佛想通過(guò)目光把這種精神注入到每個(gè)人的身上,就像武俠小說(shuō)中通過(guò)手掌將內(nèi)功傳輸給他人一樣。并不是每個(gè)人都能理解冒號(hào)的用心,但都或多或少地感受到一種異樣的氣氛。
“關(guān)于OOP今天就談到這里。”冒號(hào)恢復(fù)了常態(tài),“請(qǐng)不要奇怪為何如此流行的編程范式我卻一帶而過(guò),那是因?yàn)槟銈儗?duì)它相對(duì)比較熟悉,而我們這一輪只是在作熱身運(yùn)動(dòng),以后再作專(zhuān)項(xiàng)訓(xùn)練。在結(jié)束之前,我們引進(jìn)一個(gè)新視點(diǎn):過(guò)程式編程的模塊以函數(shù)為單位,OOP的模塊以對(duì)象為單位,二者的區(qū)別是:函數(shù)是被動(dòng)的實(shí)體,對(duì)象是主動(dòng)的實(shí)體。過(guò)程式程序的世界是君主制的,主函數(shù)是國(guó)王,其他函數(shù)是臣民,等級(jí)分明,所有臣民在聽(tīng)命于上級(jí)的同時(shí)也對(duì)下級(jí)發(fā)號(hào)施令,最終為國(guó)王服務(wù);OO程序的世界是民主制的,所有對(duì)象都是獨(dú)立而平等的公民,有權(quán)利保護(hù)自己的財(cái)產(chǎn)和隱私并向他人尋求服務(wù),同時(shí)有義務(wù)為他人提供承諾的服務(wù),公民之間通過(guò)信息交流來(lái)協(xié)作完成各種任務(wù)。”
眾人頓覺(jué)耳目為之一新。
,插語(yǔ)
[1]所謂基于對(duì)象的,有兩種不同的涵義。一種指“限制版”的OOP,即具備對(duì)象概念,但不具備OOP的一些其他特征,如繼承或多態(tài)等。Visual Basic正屬于此類(lèi)。另一種指基于原型的(prototype-based),或者說(shuō)基于實(shí)例的(instance-based),而不像通常OOP是基于類(lèi)的(class-based)。JavaScript、NewtonScript、MOO等語(yǔ)言即屬此類(lèi)。
[2]這里所謂“純粹的OOP”并非指一般意義上的“pure OOP”(即所謂的“一切都是對(duì)象”),而指單純的、不含其他范式的OOP。
[3]出自Fred Brooks的著名文章《no silver bullet》。他認(rèn)為沒(méi)有一項(xiàng)技術(shù)或管理方法的發(fā)展能保證,在十年內(nèi)讓軟件的生產(chǎn)力、可靠性或簡(jiǎn)潔性等方面提高一個(gè)數(shù)量級(jí)。常用來(lái)泛指沒(méi)有一項(xiàng)軟件技術(shù)或方法是萬(wàn)能的。
[4]更準(zhǔn)確地說(shuō),這是前文提到的結(jié)構(gòu)化編程思想。
。總結(jié)
· OOP大多是命令式的,但也有函數(shù)式的和邏輯式的OO語(yǔ)言。
· OOP的核心思想可以歸納為:以數(shù)據(jù)為中心組織邏輯,將系統(tǒng)視為相互作用的對(duì)象集合,并利用繼承與多態(tài)來(lái)增強(qiáng)重用性。
· OOP既不能脫離其他范式,也絕非適用于一切應(yīng)用。
· 可重用性、可擴(kuò)展性和靈活性是所有范式和語(yǔ)言的共同目標(biāo),并非OOP所獨(dú)有。
· 與其說(shuō)OOP更具重用性,不如說(shuō)更具易用性。
· 過(guò)程式編程重在過(guò)程,自頂向下,逐步求精。
· 對(duì)象式編程重在數(shù)據(jù),自底向上,逐步合并。
· 過(guò)程式程序的世界是君主制的,OO程序的世界是民主制的。
“”參考
[1] Wikipedia.Object-oriented programming.http://en.wikipedia.org/wiki/Object-oriented_programming
posted on 2008-11-04 00:20 鄭暉 閱讀(1436) 評(píng)論(3) 編輯 收藏 所屬分類(lèi): 冒號(hào)課堂