本頁使用了標題或全文手工轉換

物件導向程式設計

維基百科,自由的百科全書
前往: 導覽搜尋
中國大陸 面向對象程序設計
臺灣 物件導向程式設計
港澳 物件導向程式設計

物件導向程式設計英語:Object-oriented programming縮寫OOP)是種具有物件概念的程式編程典範,同時也是一種程式開發的抽象方針。它可能包含資料、屬性、程式碼方法。物件則指的是類別的例項。它將物件作為程式的基本單元,將程式和資料封裝其中,以提高軟體的重用性、靈活性和擴充功能性,物件裡的程式可以存取及經常修改物件相關連的資料。在物件導向程式編程裡,電腦程式會被設計成彼此相關的物件[1][2]

物件導向程式設計可以看作一種在程式中包含各種獨立而又互相呼叫的物件的思想,這與傳統的思想剛好相反:傳統的程式設計主張將程式看作一系列函式的集合,或者直接就是一系列對電腦下達的指令。物件導向程式設計中的每一個物件都應該能夠接受資料、處理資料並將資料傳達給其它物件,因此它們都可以被看作一個小型的「機器」,即物件。目前已經被證實的是,物件導向程式設計推廣了程式的靈活性和可維護性,並且在大型專案設計中廣為應用。此外,支持者聲稱物件導向程式設計要比以往的做法更加便於學習,因為它能夠讓人們更簡單地設計並維護程式,使得程式更加便於分析、設計、理解。反對者在某些領域對此予以否認。

當我們提到物件導向的時候,它不僅指一種程式設計方法。它更多意義上是一種程式開發方式。在這一方面,我們必須了解更多關於物件導向系統分析物件導向設計(Object Oriented Design,簡稱OOD)方面的知識。許多流行的程式語言是物件導向的,它們的風格就是會透由物件來創出實例。

重要的物件導向程式語言包含Common LispPythonC++Objective-CSmalltalkDelphiJavaSwiftC#PerlRubyPHP等。

特徵[編輯]

物件導向程式編程的定義是使用「物件」來做設計,但並非所有的程式語言都直接支援「物件導向程式編程」相關技術與結構。對於OOP的準確定義及其本意存在著不少爭論。通常,OOP被理解為一種將程式分解為封裝資料及相關操作的模組而進行的編程方式。有別於其它編程方式,OOP中的與某資料類別型相關的一系列操作都被有機地封裝到該資料類別型當中,而非散放於其外,因而OOP中的資料類別型不僅有著狀態,還有著相關的行為。

OOP理論,及與之同名的OOP實踐相結合創造出了新的一個編程架構;OOP思想被廣泛認為是非常有用的,以致一套新的編程範型被創造了出來。(其它的編程範型例如函數語言程式設計或程序式編程專注於程式執行的過程,而邏輯編程專注於引發程式代碼執行的斷言)。對面向模擬系統的語言(如:SIMULA 67)的研究及對高可靠性系統架構(如:高效能作業系統和CPU的架構)的研究最終導致了OOP的誕生。其中由Deborah J. Armstrong進行的長達40年之久的電腦著作調查中,顯示出了一系列物件導向程式設計的基本理論。物件導向程式特徵被條列如下[3][4][5][6]

分享非物件導向程式前身語言[編輯]

物件導向程式設計通常共享高階編程語言的低階功能。可用於建構一個程式的基本工具包括:

類別與物件[編輯]

支援物件導向編程語言通常利用繼承其他類別達到代碼重用和可擴展性的特性。而類別有兩個主要的概念:

  • 類別(Class):定義了一件事物的抽象特點。類別的定義包含了資料的形式以及對資料的操作。
  • 物件:是類別的實例。

其中類別別(Class)定義了一件事物的抽象特點。類別的定義包含了資料的形式以及對資料的操作。舉例來說,「」這個類別會包含狗的一切基礎特徵,即所有「狗」都共有的特徵或行為,例如它的孕育、毛皮顏色和吠叫的能力。類別可以為程式提供模版和結構。一個類別的方法和屬性被稱為「成員」。 我們來看一段虛擬碼

類別 
開始
    公有成員:
        吠叫():
    私有成員:
        毛皮顏色:
        孕育:
結束

在這串代碼中,我們聲明了一個類別,這個類別具有一些狗的基本特徵。關於公有成員私有成員,請參見下面的繼承性一節。

物件(Object)是類別的例項。物件有時會對應到現實世界中的事物,舉例來說,一個圖形程式可能有圓形、矩形與畫面等物件,一個線上購物系統可能有購物車、顧客與產品等類別。[7]。有時物件會表示更抽象的實體,比如一個被開啟的檔案或是一個提供美國慣用量測轉換的服務。每個物件就是一個特定類別的實例(例如,名稱是「瑪麗」的物件可能是類別雇員的一個實例)。程式在物件導向編程當中被視為方法,變數被視為成員或屬性。例如,「」這個類別列舉狗的特點,從而使這個類別定義了世界上所有的狗。而萊絲這個物件則是一條具體的狗,它的屬性也是具體的。狗有皮毛顏色,而萊絲的皮毛顏色是棕白色的。因此,萊絲就是狗這個類別的一個例項。一個具體物件屬性的值被稱作它的「狀態」。(系統給物件分配記憶體空間,而不會給類別分配記憶體空間。這很好理解,類別是抽象的系統不可能給抽象的東西分配空間,而物件則是具體的。)

假設我們已經在上面定義了狗這個類別,我們就可以用這個類別來定義物件:

定義萊絲
萊絲.毛皮顏色:棕白色
萊絲.吠叫()

我們無法讓狗這個類別去吠叫,但是我們可以讓物件「萊絲」去吠叫,正如狗可以吠叫,但沒有具體的狗就無法吠叫。

類別和物件就好比是「實型」和「1.23」,「實型」是一種資料的類別型,而「1.23」是一個真正的「實數」(即物件)。所有的「實數」都具有「實型」所描訴的特徵,如「實數的大小」,系統則分配記憶體給「實數」儲存具體的數值。

動態配置與訊息傳遞機制[編輯]

定義上動態配置是指方法會隨著實例動態的改變。而訊息傳遞機制(Message Passing)是指一個物件通過接受訊息、處理訊息、傳出訊息或使用其他類別的方法來實作一定功能。如:萊絲可以通過吠叫引起的注意,從而導致一系列的事發生。

封裝性[編輯]

具備封裝性(Encapsulation)的物件導向程式設計隱藏了某一方法的具體執行步驟,取而代之的是通過訊息傳遞機制傳送訊息給它。封裝是通過限制只有特定類別的物件可以存取這一特定類別的成員,而它們通常利用介面實作訊息的傳入傳出。舉個例子,介面能確保幼犬這一特徵只能被賦予狗這一類別。通常來說,成員會依它們的存取權限被分為3種:公有成員私有成員以及保護成員。有些語言更進一步:Java可以限制同一包內不同類別的存取;C#VB.NET保留了為類別的成員聚集準備的關鍵字:internal(C#)和Friend(VB.NET);Eiffel語言則可以讓使用者指定哪個類別可以存取所有成員。

具備封裝性(Encapsulation)的物件導向程式設計隱藏了某一方法的具體執行步驟,取而代之的是通過訊息傳遞機制傳送訊息給它。因此,舉例來說,「狗」這個類別有「吠叫()」的方法,這一方法定義了狗具體該通過什麼方法吠叫。但是,萊絲的朋友並不知道它到底是如何吠叫的。

從例項來看:

/* 一個程序導向的程式會這樣寫: */
定義萊絲
萊絲.設定音調(5)
萊絲.吸氣()
萊絲.吐氣()

/* 而當狗的吠叫被封裝到類別中,任何人都可以簡單地使用: */
定義萊絲
萊絲.吠叫()

繼承[編輯]

繼承性(Inheritance)是指,在某種情況下,一個類別會有「子類別」。子類別比原本的類別(稱為父類別)要更加具體化。例如,「」這個類別可能會有它的子類別牧羊犬」和「吉娃娃犬」。在這種情況下,「萊絲」可能就是牧羊犬的一個例項。子類別會繼承父類別的屬性行為,並且也可包含它們自己的。我們假設「狗」這個類別有一個方法(行為)叫做「吠叫()」和一個屬性叫做「毛皮顏色」。它的子類別(前例中的牧羊犬和吉娃娃犬)會繼承這些成員。這意味著程式設計師只需要將相同的代碼寫一次。

在虛擬碼中我們可以這樣寫:

類別牧羊犬:繼承

定義萊絲牧羊犬
萊絲.吠叫()    /* 注意這裡呼叫的是狗這個類別的吠叫方法。*/

回到前面的例子,「牧羊犬」這個類別可以繼承「毛皮顏色」這個屬性,並指定其為棕白色。而「吉娃娃犬」則可以繼承「吠叫()」這個方法,並指定它的音調高於平常。子類別也可以加入新的成員,例如,「吉娃娃犬」這個類別可以加入一個方法叫做「顫抖()」。設若用「牧羊犬」這個類別定義了一個例項「萊絲」,那麼萊絲就不會顫抖,因為這個方法是屬于吉娃娃犬的,而非牧羊犬。事實上,我們可以把繼承理解為「是」或「屬於」。萊絲「是」牧羊犬,牧羊犬「屬於」狗類別。因此,萊絲既得到了牧羊犬的屬性,又繼承了狗的屬性。 我們來看虛擬碼:

類別吉娃娃犬:繼承
開始
   公有成員:
      顫抖()
結束
類別牧羊犬:繼承

定義萊絲牧羊犬
萊絲.顫抖()    /* 錯誤:顫抖是吉娃娃犬的成員方法。 */

當一個類別從多個父類別繼承時,我們稱之為「多重繼承」。如一隻狗既是吉娃娃犬又是牧羊犬(雖然事實上並不合邏輯)。多重繼承並不總是被支援的,因為它很難理解,又很難被好好使用。

多型[編輯]

多型(Polymorphism)是指由繼承而產生的相關的不同的類別,其物件對同一訊息會做出不同的回應[8]。例如,狗和雞都有「叫()」這一方法,但是呼叫狗的「叫()」,狗會吠叫;呼叫雞的「叫()」,雞則會啼叫。 我們將它體現在虛擬碼上:

類別
開始
   公有成員:
       叫()
       開始
          吠叫()
       結束
結束

類別
開始
   公有成員:
       叫()
       開始
          啼叫()
       結束
結束

定義萊絲
定義魯斯特
萊絲.叫()
魯斯特.叫()

這樣,雖然同樣是做出這一種行為,但萊絲和魯斯特具體做出的表現方式將大不相同。多型性的概念可以用在運算子過載上,本文不再贅述。

抽象性[編輯]

抽象(Abstraction)是簡化複雜的現實問題的途徑,它可以為具體問題找到最恰當的類別定義,並且可以在最恰當的繼承級別解釋問題。舉例說明,萊絲在大多數時候都被當作一條狗,但是如果想要讓它做牧羊犬做的事,你完全可以呼叫牧羊犬的方法。如果狗這個類別還有動物的父類別,那麼你完全可以視萊絲為一個動物。

歷史[編輯]

物件導向程式設計的雛形,早在1960年的Simula語言中即可發現,當時的程式設計領域正面臨著一種危機:在軟硬體環境逐漸複雜的情況下,軟體如何得到良好的維護?物件導向程式設計在某種程度上通過強調可重複性解決了這一問題。20世紀70年代的Smalltalk語言在物件導向方面堪稱經典——以至於30年後的今天依然將這一語言視為物件導向語言的基礎。

電腦科學中物件和例項概念的最早萌芽可以追溯到麻省理工學院PDP-1系統。這一系統大概是最早的基於容量架構(capability based architecture)的實際系統。另外1963年Ivan Sutherland的Sketchpad應用中也蘊含了同樣的思想。物件作為編程實體最早是於1960年代由Simula 67語言引入思維。Simula這一語言是奧利-約翰·達爾克利斯登·奈加特在挪威奧斯陸電腦中心為模擬環境而設計的。(據說,他們是為了模擬船隻而設計的這種語言,並且對不同船隻間屬性的相互影響感興趣。他們將不同的船隻歸納為不同的類別,而每一個物件,基於它的類別,可以定義它自己的屬性和行為。)這種辦法是分析式程式的最早概念體現。在分析式程式中,我們將真實世界的物件對映到抽象的物件,這叫做「模擬」。Simula不僅引入了「類別」的概念,還應用了例項這一思想——這可能是這些概念的最早應用。

20世紀70年代全錄PARC研究所發明的Smalltalk語言將物件導向程式設計的概念定義為,在基礎運算中,對物件訊息的廣泛應用。Smalltalk的建立者深受Simula 67的主要思想影響,但Smalltalk中的物件是完全動態的——它們可以被建立、修改並銷毀,這與Simula中的靜態物件有所區別。此外,Smalltalk還引入了繼承性的思想,它因此一舉超越了不可建立例項的程式設計模型和不具備繼承性的Simula。此外,Simula 67的思想亦被應用在許多不同的語言,如LispPascal

物件導向程式設計在80年代成為了一種主導思想,這主要應歸功於C++——C語言的擴充版。在圖形化使用者介面(GUI)日漸崛起的情況下,物件導向程式設計很好地適應了潮流。GUI和物件導向程式設計的緊密關聯在Mac OS X中可見一斑。Mac OS X是由Objective-C語言寫成的,這一語言是一個仿Smalltalk的C語言擴充版。物件導向程式設計的思想也使事件處理式的程式設計更加廣泛被應用(雖然這一概念並非僅存在於物件導向程式設計)。一種說法是,GUI的引入極大地推動了物件導向程式設計的發展。

蘇黎世聯邦理工學院的尼克勞斯·維爾特和他的同事們對抽象資料和模組化程式設計進行了研究。Modula-2將這些都包括了進去,而Oberon則包括了一種特殊的物件導向方法——不同於SmalltalkC++

物件導向的特性也被加入了當時較為流行的語言:AdaBASICLispFortranPascal以及種種。由於這些語言最初並沒有物件導向的設計,故而這種糅合常常會導致相容性和維護性的問題。與之相反的是,「純正的」物件導向語言卻缺乏一些程式設計師們賴以生存的特性。在這一大環境下,開發新的語言成為了當務之急。作為先行者,Eiffel成功地解決了這些問題,並成為了當時較受歡迎的語言。

在過去的幾年中,Java語言成為了廣為應用的語言,除了它與CC++語法上的近似性。Java的可移植性是它的成功中不可磨滅的一步,因為這一特性,已吸引了龐大的程式設計師群的投入。

在最近的電腦語言發展中,一些既支援物件導向程式設計,又支援程序導向程式設計的語言悄然浮出水面。它們中的佼佼者有PythonRuby等等。

正如程序導向程式設計使得結構化程式設計的技術得以提升,現代的物件導向程式設計方法使得對設計模式的用途、契約式設計建模語言(如UML)技術也得到了一定提升。

物件導向編程語言[編輯]

支援部分或絕大部分物件導向特性的語言即可稱為基於物件的或物件導向的語言。Simula (1967)被視為第一個具有物件導向特性的語言。早期,完全物件導向的語言主要包括Smalltalk等語言,目前較為流行的語言中有JavaC#Eiffel等。隨著軟體工業的發展,比較早的程序導向的語言在近些年的發展中也紛紛吸收了許多物件導向的概念,比如CC++,C→Objective-CBASICVisual BasicVisual Basic .NETPascalObject PascalAdaAda95。「純粹」的物件導向語言, 因為所有的東西都是由物件所組成,例如: Eiffel, Emerald,[9] JADE, Obix, Ruby, Scala, Smalltalk, Self.

腳本中的OOP[編輯]

近年來,物件導向的程式設計越來越流行於手稿語言中。PythonRuby是建立在OOP原理的指令碼語言,PerlPHP亦分別在Perl 5和PHP 4時加入物件導向特性。

參見[編輯]

參考文獻[編輯]

  1. ^ Kindler, E.; Krivy, I. Object-Oriented Simulation of systems with sophisticated control. International Journal of General Systems: 313–343. 2011. 
  2. ^ Lewis, John; Loftus, William. Java Software Solutions Foundations of Programming Design 6th ed. Pearson Education Inc. 2008. ISBN 0-321-53205-8. , section 1.6 "Object-Oriented Programming"
  3. ^ Deborah J. Armstrong. The Quarks of Object-Oriented Development. A survey of nearly 40 years of computing literature which identified a number of fundamental concepts found in the large majority of definitions of OOP, in descending order of popularity: Inheritance, Object, Class, Encapsulation, Method, Message Passing, Polymorphism, and Abstraction.
  4. ^ John C. Mitchell, Concepts in programming languages, Cambridge University Press, 2003, ISBN 0-521-78098-5, p.278. Lists: Dynamic dispatch, abstraction, subtype polymorphism, and inheritance.
  5. ^ Michael Lee Scott, Programming language pragmatics, Edition 2, Morgan Kaufmann, 2006, ISBN 0-12-633951-1, p. 470. Lists encapsulation, inheritance, and dynamic dispatch.
  6. ^ Pierce, Benjamin. Types and Programming Languages. MIT Press. 2002. ISBN 0-262-16209-1. , section 18.1 "What is Object-Oriented Programming?" Lists: Dynamic dispatch, encapsulation or multi-methods (multiple dispatch), subtype polymorphism, inheritance or delegation, open recursion ("this"/"self")
  7. ^ Booch, Grady. Software Engineering with Ada. Addison Wesley. 1986: 220. ISBN 978-0805306088. Perhaps the greatest strength of an object-oriented approach to development is that it offers a mechanism that captures a model of the real world. 
  8. ^ 譚浩強:《C++物件導向程式設計》,清華大學出版社,2006年1月第一版。ISBN 978-7-302-12315-6
  9. ^ The Emerald Programming Language. 2011-02-26. 

延伸閱讀[編輯]

外部連結[編輯]

Wikibooks-logo.svg
您可以在維基教科書中尋找此百科條目的相關電子教程: