百科解釋
目錄·概述·基本理論·OOP名詞釋意·面向?qū)ο蟮恼Z言·歷史 面向?qū)ο蟪绦蛟O(shè)計(英語:Object-oriented programming,縮寫:OOP),指一種程序設(shè)計范型,同時也是一種程序開發(fā)的方法論。它將對象作為程序的基本單元,將程序和數(shù)據(jù)封裝其中,以提高軟件的重用性、靈活性和擴展性。[1] 當(dāng)我們提到面向?qū)ο蟮臅r候,它不僅指一種程序設(shè)計方法。它更多意義上是一種程序開發(fā)方式。在這一方面,我們必須了解更多關(guān)于面向?qū)ο笙到y(tǒng)分析和面向?qū)ο笤O(shè)計(Object Oriented Design,簡稱OOD)方面的知識。 概述 面向?qū)ο蟪绦蛟O(shè)計的雛形,早在1960年的Simula語言中即可發(fā)現(xiàn),當(dāng)時的程序設(shè)計領(lǐng)域正面臨著一種危機:在軟硬件環(huán)境逐漸復(fù)雜的情況下,軟件如何得到良好的維護?面向?qū)ο蟪绦蛟O(shè)計在某種程度上通過強調(diào)可重復(fù)性解決了這一問題。20世紀(jì)70年代的SmallTalk語言在面向?qū)ο蠓矫婵胺Q經(jīng)典——以至于30年后的今天依然將這一語言視為面向?qū)ο笳Z言的基礎(chǔ)。 面向?qū)ο蟪绦蛟O(shè)計可以被視作一種在程序中包含各種獨立而又互相調(diào)用的單位和對象的思想,這與傳統(tǒng)的思想剛好相反:傳統(tǒng)的面向過程程序設(shè)計主張將程序看作一系列函數(shù)的集合,或者直接就是一系列對電腦下達(dá)的指令。面向?qū)ο蟪绦蛟O(shè)計中的每一個對象都應(yīng)該能夠接受數(shù)據(jù)、處理數(shù)據(jù)并將數(shù)據(jù)傳達(dá)給其它對象,因此它們都可以被看作一個小型的“機器”,或者說是負(fù)有責(zé)任的角色。 目前已經(jīng)被證實的是,面向?qū)ο蟪绦蛟O(shè)計推廣了程序的靈活性和可維護性,并且在大型項目設(shè)計中廣為應(yīng)用。 此外,支持者聲稱面向?qū)ο蟪绦蛟O(shè)計要比以往的做法更加便于學(xué)習(xí),因為它能夠讓人們更簡單地設(shè)計并維護程序,使得程序更加便于分析、設(shè)計、理解。反對者在某些領(lǐng)域?qū)Υ擞枰苑裾J(rèn)。 基本理論 一項由 Deborah J. Armstrong 進(jìn)行的長達(dá)40年之久的計算機著作調(diào)查顯示出了一系列面向?qū)ο蟪绦蛟O(shè)計的基本理論。它們是: 類 類(Class)定義了一件事物的抽象特點。通常來說,類定義了事物的屬性和它可以做到的(它的行為)。舉例來說,“狗”這個類會包含狗的一切基礎(chǔ)特征,例如它的孕育、毛皮顏色和吠叫的能力。類可以為程序提供模版和結(jié)構(gòu)。一個類的方法和屬性被稱為“成員”。 我們來看一段偽代碼: <code>類狗 開始 私有成員: 孕育 毛皮顏色 公有成員: 吠叫() 結(jié)束 </code> 在這串代碼中,我們聲明了一個類,這個類具有一些狗的基本特征。關(guān)于公有成員和私有成員,請參見下面的繼承性一節(jié)。 對象 對象(Object)是類的實例。例如,“狗”這個類列舉狗的特點,從而使這個類定義了世界上所有的狗。而萊絲這個對象則是一條具體的狗,它的屬性也是具體的。狗有皮毛顏色,而萊絲的皮毛顏色是棕白色的。因此,萊絲就是狗這個類的一個實例。一個具體對象屬性的值被稱作它的“狀態(tài)”。 假設(shè)我們已經(jīng)在上面定義了狗這個類,我們就可以用這個類來定義對象: 定義萊絲是狗 萊絲.毛皮顏色:=棕白色 萊絲.吠叫() 我們無法讓狗這個類去吠叫,但是我們可以讓對象“萊絲”去吠叫,正如狗可以吠叫,但沒有具體的狗就無法吠叫。 方法 方法(Method)是一個類能做的事情,但方法并沒有去做這件事。作為一條狗,萊絲是會吠叫的,因此“吠叫()”就是它的一個方法。與此同時,它可能還會有其它方法,例如“坐下()”,或者“吃()”。 對一個具體對象的方法進(jìn)行調(diào)用并不影響其它對象,正如所有的狗都會叫,但是你讓一條狗叫不代表所有的狗都叫。 如下例: 定義萊絲是狗 定義泰爾是狗 萊絲.吠叫() 則泰爾是不會吠叫的,因為這里的吠叫只是對對象“萊絲”進(jìn)行的。 消息傳遞機制 一個對象通過接受消息、處理消息、傳出消息或使用其他類的方法來實現(xiàn)一定功能,這叫做消息傳遞機制(Message Passing)。 繼承性 繼承性(Inheritance)是指,在某種情況下,一個類會有“子類”。子類比原本的類(稱為父類)要更加具體化,例如,“狗”這個類可能會有它的子類“牧羊犬”和“吉娃娃犬”。在這種情況下,“萊絲”可能就是牧羊犬的一個實例。子類會繼承父類的屬性和行為,并且也可包含它們自己的。我們假設(shè)“狗”這個類有一個方法叫做“吠叫()”和一個屬性叫做“毛皮顏色”。它的子類(前例中的牧羊犬和吉娃娃犬)會繼承這些成員。這意味著程序員只需要將相同的代碼寫一次。 在偽代碼中我們可以這樣寫: 類牧羊犬:繼承狗 定義萊絲是牧羊犬 萊絲.吠叫() /* 注意這里調(diào)用的是狗這個類的吠叫屬性。 */ 回到前面的例子,“牧羊犬”這個類可以繼承“毛皮顏色”這個屬性,并指定其為棕白色。而“吉娃娃犬”則可以繼承“吠叫()”這個方法,并指定它的音調(diào)高于平常。子類也可以加入新的成員,例如,“吉娃娃犬”這個類可以加入一個方法叫做“顫抖()”。設(shè)若用“牧羊犬”這個類定義了一個實例“萊絲”,那么萊絲就不會顫抖,因為這個方法是屬于吉娃娃犬的,而非牧羊犬。事實上,我們可以把繼承理解為“是”。例如,萊絲“是”牧羊犬,牧羊犬“是”狗。因此,萊絲既繼承了牧羊犬的屬性,又繼承了狗的屬性。 我們來看偽代碼: 類吉娃娃犬:繼承狗 開始 公有成員: 顫抖() 結(jié)束 類牧羊犬:繼承狗 定義萊絲是牧羊犬 萊絲.顫抖() /* 錯誤:顫抖是吉娃娃犬的成員方法。 */ 當(dāng)一個類從多個父類繼承時,我們稱之為“多重繼承”。多重繼承并不總是被支持的,因為它很難理解,又很難被好好使用。 封裝性 具備封裝性(Encapsulation)的面向?qū)ο蟪绦蛟O(shè)計隱藏了某一方法的具體執(zhí)行步驟,取而代之的是通過消息傳遞機制傳送消息給它。因此,舉例來說,“狗”這個類有”吠叫()”的方法,這一方法定義了狗具體該通過什么方法吠叫。但是,萊絲的朋友蒂米并不需要知道它到底如何吠叫。 從實例來看: /* 一個面向過程的程序會這樣寫: */ 定義萊絲 萊絲.設(shè)置音調(diào)(5) 萊絲.吸氣() 萊絲.吐氣() /* 而當(dāng)狗的吠叫被封裝到類中,任何人都可以簡單地使用: */ 定義萊絲是狗 萊絲.吠叫() 封裝是通過限制只有特定類的實例可以訪問這一特定類的成員,而它們通常利用接口實現(xiàn)消息的傳入傳出。舉個例子,接口能確保幼犬這一特征只能被賦予狗這一類。通常來說,成員會依它們的訪問權(quán)限被分為3種:公有成員、私有成員以及保護成員。有些語言更進(jìn)一步:Java可以限制同一包內(nèi)不同類的訪問;C#和VB.NET保留了為類的成員聚集準(zhǔn)備的關(guān)鍵字:internal(C#)和Friend(VB.NET);Eiffel語言則可以讓用戶指定哪個類可以訪問所有成員。 多態(tài)性 多態(tài)性(Polymorphism)指方法在不同的類中調(diào)用可以實現(xiàn)的不同結(jié)果。因此,2個甚至更多的類可以對同一消息作出不同的反應(yīng)。舉例來說,狗和雞都有“叫()”這一方法,但是調(diào)用狗的“叫()”,狗會吠叫;調(diào)用雞的“叫()”,雞則會啼叫。 我們將它體現(xiàn)在偽代碼上: 類狗 開始 公有成員: 叫() 開始 吠叫() 結(jié)束 結(jié)束 類雞 開始 公有成員: 叫() 開始 啼叫() 結(jié)束 結(jié)束 定義萊絲是狗 定義魯斯特是雞 萊絲.叫() 魯斯特.叫() 這樣,同樣是叫,萊絲和魯斯特做出的反應(yīng)將大不相同。多態(tài)性的概念可以用在運算符重載上,本文不再贅述。 抽象性 抽象(Abstraction)是簡化復(fù)雜的現(xiàn)實問題的途徑,它可以為具體問題找到最恰當(dāng)?shù)念惗x,并且可以在最恰當(dāng)?shù)睦^承級別解釋問題。舉例說明,萊絲在大多數(shù)時候都被當(dāng)作一條狗,但是如果想要讓它做牧羊犬做的事,你完全可以調(diào)用牧羊犬的方法。如果狗這個類還有動物的父類,那么你完全可以視萊絲為一個動物。 OOP名詞釋意 編程范型 對于OOP的準(zhǔn)確定義及其本意存在著不少爭論。 通常,OOP被理解為一種將程序分解為封裝數(shù)據(jù)及相關(guān)操作的模塊而進(jìn)行的編程方式。有別于其它編程方式,OOP中的與某數(shù)據(jù)類型相關(guān)的一系列操作都被有機地封裝到該數(shù)據(jù)類型當(dāng)中,而非散放于其外,因而OOP中的數(shù)據(jù)類型不僅有著狀態(tài),還有著相關(guān)的行為。OOP理論,及與之同名的OOP實踐相結(jié)合創(chuàng)造出了新的一個編程架構(gòu);OOP思想被廣泛認(rèn)為是非常有用的,以致一套新的編程范型被創(chuàng)造了出來。(其它的編程范型例如函數(shù)式編程或過程序編程專注于程序運行的過程,而邏輯編程專注于引發(fā)程序代碼執(zhí)行的斷言) 對面向模擬系統(tǒng)的語言(如:SIMULA 67)的研究及對高可靠性系統(tǒng)架構(gòu)(如:高性能操作系統(tǒng)和CPU的架構(gòu))的研究最終導(dǎo)致了OOP的誕生。 一些專家認(rèn)為Object-Orientation中的Object的本意來自于其在語法領(lǐng)域的意義,即應(yīng)將其理解為“賓語”或“操作對象”,而非一般的“對象”或“對象”。我們所見到的軟件的運行請求通常都是Subject-Oriented的,即“面向主語的”或“面向操作者的”,然而這樣將使得對操作者對象的設(shè)計變得困難而復(fù)雜。有鑒于此,部分研究人員開始了對“面向操作對象”的思考。這又一次產(chǎn)生了新的編程范型,這是前邊提到的“面向操作者”的思考模式的一項革新。 依照“面向操作對象”的原則,在程序語句中的動詞應(yīng)該被劃分到操作對象的類型之中,而與該動詞請求相關(guān)的邏輯關(guān)系也就因此將在操作對象中處理。以下是采用“面向操作對象”的方式翻譯“面向操作者”的一些例子: 面向操作者:銷售系統(tǒng)保存交易記錄。 面向操作對象:交易記錄在接受到銷售系統(tǒng)的一條請求消息后將自身保存。 面向操作者:銷售系統(tǒng)打印收據(jù)。 面向操作對象:收據(jù)在接收到銷售系統(tǒng)的一條請求消息后將自身打印。 面向?qū)ο蟮恼Z言 支持部分或絕大部分面向?qū)ο筇匦缘恼Z言即可稱為基于對象的或面向?qū)ο蟮恼Z言。 早期,完全面向?qū)ο蟮恼Z言主要包括Smalltalk等語言,目前較為流行的語言中有Java、C#、Eiffel等。隨著軟件工業(yè)的發(fā)展,比較早的面向過程的語言在近些年的發(fā)展中也紛紛吸收了許多面向?qū)ο蟮母拍,比如C->C++,BASIC->Visual Basic->Visual Basic .NET,Pascal->Object Pascal,Ada->Ada95。 歷史 對象和實例的最早概念出自麻省理工大學(xué)的PDP-1系統(tǒng)。這一系統(tǒng)大概是capability based architecture的最早示例。另一個早期的事例是1963年Ivan Sutherland開發(fā)的Sketchpad;但是,這并非是一種編程思想,而只是一個程序。 對象最早在20世紀(jì)60年代的Simula 67中被引入程序設(shè)計中。Simula這一語言是Ole-Johan Dahl和Kristen Nygaard在奧斯陸計算機中心為模擬環(huán)境而設(shè)計的。(據(jù)說,他們是為了模擬船只而設(shè)計的這種語言,并且對不同船只間屬性的相互影響感興趣。他們將不同的船只歸納為不同的類,而每一個對象,基于它的類,可以定義它自己的屬性和行為。)這種辦法是分析式程序的最早概念體現(xiàn)。在分析式程序中,我們將真實世界的對象映射到抽象的對象,這叫做“模擬”。Simula不僅引入了“類”的概念,還應(yīng)用了實例這一思想——這可能是這些概念的最早應(yīng)用。 20世紀(jì)70年代施樂PARC研究所發(fā)明的Smalltalk語言將面向?qū)ο蟪绦蛟O(shè)計的概念定義為,在基礎(chǔ)運算中,對對象和消息的廣泛應(yīng)用。Smalltalk的創(chuàng)建者深受Simula 67的主要思想影響,但Smalltalk中的對象是完全動態(tài)的——它們可以被創(chuàng)建、修改并銷毀,這與Simula中的靜態(tài)對象有所區(qū)別。此外,Smalltalk還引入了繼承性的思想,它因此一舉超越了不可創(chuàng)建實例的程序設(shè)計模型和不具備繼承性的Simula。 此外,Simula 67的思想亦被應(yīng)用在許多不同的語言,如Lisp、Pascal。 面向?qū)ο蟪绦蛟O(shè)計在80年代成為了一種主導(dǎo)思想,這主要應(yīng)歸功于C++——C語言的擴充版。在圖形用戶界面(GUI)日漸崛起的情況下,面向?qū)ο蟪绦蛟O(shè)計很好地適應(yīng)了潮流。GUI和面向?qū)ο蟪绦蛟O(shè)計的緊密關(guān)聯(lián)在Mac OS X中可見一斑。Mac OS X是由面向?qū)ο驝語言寫成的,這一語言是一個仿Smalltalk的C語言擴充版。面向?qū)ο蟪绦蛟O(shè)計的思想也使事件處理式的程序設(shè)計更加廣泛被應(yīng)用(雖然這一概念并非僅存在于面向?qū)ο蟪绦蛟O(shè)計)。一種說法是,GUI的引入極大地推動了面向?qū)ο蟪绦蛟O(shè)計的發(fā)展。 在ETH Zürich(英文),Niklaus Wirth 和他的同事們對抽象數(shù)據(jù)和模塊化程序設(shè)計進(jìn)行了調(diào)查。Modula-2將這些都包括了進(jìn)去,而Oberon則包括了一種特殊的面向?qū)ο蠓椒ā煌赟malltalk與C++。 面向?qū)ο蟮奶匦砸脖患尤肓水?dāng)時較為流行的語言:Ada、BASIC、Lisp、Fortran、Pascal以及種種。由于這些語言最初并沒有面向?qū)ο蟮脑O(shè)計,故而這種糅合常常會導(dǎo)致兼容性和維護性的問題。與之相反的是,“純正的”面向?qū)ο笳Z言卻缺乏一些程序員們賴以生存的特性。在這一大環(huán)境下,開發(fā)新的語言成為了當(dāng)務(wù)之急。作為先行者,Eiffel成功地解決了這些問題,并成為了當(dāng)時較受歡迎的語言。 在過去的幾年中,Java語言成為了廣為應(yīng)用的語言,除了它與C和C++語法上的近似性。Java的可移植性是它的成功中不可磨滅的一步,因為這一特性,已吸引了龐大的程序員群的投入。 近日,一些既支持面向?qū)ο蟪绦蛟O(shè)計,又支持面向過程程序設(shè)計的語言悄然浮出水面。它們中的佼佼者有Python、Ruby等等. 正如面向過程程序設(shè)計使得結(jié)構(gòu)化程序設(shè)計的技術(shù)得以提升,現(xiàn)代的面向?qū)ο蟪绦蛟O(shè)計方法使得對設(shè)計模式的用途、契約式設(shè)計和建模語言(如UML)技術(shù)也得到了一定提升。 腳本中的OOP 近年來,面向過程程序設(shè)計越發(fā)流行于腳本語言。Python和Ruby是建立在OOP原理的腳本語言,Perl和PHP亦分別在Perl 5和PHP 4時加入面向過程特性。
移動通信網(wǎng) | 通信人才網(wǎng) | 更新日志 | 團隊博客 | 免責(zé)聲明 | 關(guān)于詞典 | 幫助