解讀面向對象的程序設計(一)
面向對象編程(ObjectOrientedProgramming,OOP,面向對象程序設計)是一種計算機編程架構。OOP的一條基本原則是計算機程序是由單個能夠起到子程序作用的單元或對象組合而成。OOP達到了軟件工程的三個主要目標:重用性、靈活性和擴展性。為了實現整體運算,每個對象都能夠接收信息、處理數據和向其它對象發送信息。OOP主要有以下的概念和組件:
組件
數據和功能一起在運行著的計算機程序中形成的單元,組件在OOP計算機程序中是模塊和結構化的基礎。
抽象性
程序有能力忽略正在處理中信息的某些方面,即對信息主要方面關注的能力。
封裝
也叫做信息封裝:確保組件不會以不可預期的方式改變其它組件的內部狀態;只有在那些提供了內部狀態改變方法的組件中,才可以訪問其內部狀態。每類組件都提供了一個與其它組件聯系的接口,并規定了其它組件進行調用的方法。
多態性
組件的引用和類集會涉及到其它許多不同類型的組件,而且引用組件所產生的結果得依據實際調用的類型。
繼承性
允許在現存的組件基礎上創建子類組件,這統一并增強了多態性和封裝性。典型地來說就是用類來對組件進行分組,而且還可以定義新類為現存的類的擴展,這樣就可以將類組織成樹形或網狀結構,這體現了動作的通用性。
由于抽象性、封裝性、重用性以及便于使用等方面的原因,以組件為基礎的編程在腳本語言中已經變得特別流行。Python和Ruby是最近才出現的語言,在開發時完全采用了OOP的思想,而流行的Perl腳本語言從版本5開始也慢慢地加入了新的面向對象的功能組件。用組件代替“現實”上的實體成為JavaScript(ECMAScript)得以流行的原因,有論證表明對組件進行適當的組合就可以在英特網上代替HTML和XML的文檔對象模型(DOM)。
oop的基本思想
OOP的許多原始思想都來之于Simula語言,并在Smalltalk語言的完善和標準化過程中得到更多的擴展和對以前的思想的重新注解。可以說OO思想和OOPL幾乎是同步發展相互促進的。
與函數式程序設計(functional-programming)和邏輯式程序設計(logic-programming)所代表的接近于機器的實際計算模型所不同的是,OOP幾乎沒有引入精確的數學描敘,而是傾向于建立一個對象模型,它能夠近似的反映應用領域內的實體之間的關系,其本質是更接近于一種人類認知事物所采用的哲學觀的計算模型。由此,導致了一個自然的話題,那就是OOP到底是什么?[D&T1988][B.S1991].。
在OOP中,對象作為計算主體,擁有自己的名稱,狀態以及接受外界消息的接口。在對象模型中,產生新對象,舊對象銷毀,發送消息,響應消息就構成OOP計算模型的根本。
對象的產生有兩種基本方式。
一種是以原型(prototype)對象為基礎產生新的對象。
一種是以類(class)為基礎產生新對象。
原型的概念已經在認知心理學中被用來解釋概念學習的遞增特性,原型模型本身就是企圖通過提供一個有代表性的對象為基礎來產生各種新的對象,并由此繼續產生更符合實際應用的對象。而原型-委托也是OOP中的對象抽象,代碼共享機制中的一種。一個類提供了一個或者多個對象的通用性描敘。
從形式化的觀點看,類與類型有關,因此一個類相當于是從該類中產生的實例的集合。而這樣的觀點也會帶來一些矛盾,比較典型的就是在繼承體系下,子集(子類)對象和父集(父類)對象之間的行為相融性可能很難達到,這也就是OOP中常被引用的---子類型(subtype)不等于子類(subclass)[Budd2002]。而在一種所有皆對象的世界觀背景下,在類模型基礎上還誕生出了一種擁有元類(metaclass)的新對象模型。即類本身也是一種其他類的對象。
以上三種根本不同的觀點各自定義了三種基于類(class-based),基于原型(prototype-based)和基于元類(metaclass-based)的對象模型。而這三種對象模型也就導致了許多不同的程序設計語言(如果我們暫時把靜態與動態的差別放在一邊)。是的,我們經常接觸的C++,Java都是使用基于類的對象模型,但除此之外還有很多我們所沒有接觸的OOPL采用了完全不一樣的對象模型,他們是在用另外一種觀點詮釋OOP的內涵。
什么是oop的基本思想呢?
把組件的實現和接口分開,并且讓組件具有多態性。不過,兩者還是有根本的不同。oop強調在程序構造中語言要素的語法。你必須得繼承,使用類,使用對象,對象傳遞消息。gp不關心你繼承或是不繼承,它的開端是分析產品的分類,有些什么種類,他們的行為如何。
就是說,兩件東西相等意味著什么?怎樣正確地定義相等操作?不單單是相等操作那么簡單,你往深處分析就會發現“相等”這個一般觀念意味著兩個對象部分,或者至少基本部分是相等的,據此我們就可以有一個通用的相等操作。
再說對象的種類
假設存在一個順序序列和一組對于順序序列的操作。那么這些操作的語義是什么?從復雜度權衡的角度看,我們應該向用戶提供什么樣的順序序列?該種序列上存在那些操作?那種排序是我們需要的?只有對這些組件的概念型分類搞清楚了,我們才能提到實現的問題:使用模板、繼承還是宏?使用什么語言和技術?gp的基本觀點是把抽象的軟件組件和它們的行為用標準的分類學分類,出發點就是要建造真實的、高效的和不取決于語言的算法和數據結構。
當然最終的載體還是語言,沒有語言沒法編程。stl使用c++,你也可以用ada來實現,用其他的語言來實現也行,結果會有所不同,但基本的東西是一樣的。到處都要用到二分查找和排序,而這就是人們正在做的。對于容器的語義,不同的語言會帶來輕微的不同。但是基本的區別很清楚是gp所依存的語義,以及語義分解。
例如,我們決定需要一個組件swap,然后指出這個組件在不同的語言中如果工作。顯然重點是語義以及語義分類。而oop所強調的(我認為是過分強調的)是清楚的定義類之間的層次關系。oop告訴了你如何建立層次關系,卻沒有告訴你這些關系的實質。
(這段不太好理解,有一些術語可能要過一段時間才會有合適的中文翻譯——譯者)
面向對象的編程方法OOP是九十年代才流行的一種軟件編程方法。它強調對象的“抽象”、“封裝”、“繼承”、“多態”。我們講程序設計是由“數據結構”+“算法”組成的。從宏觀的角度講,OOP下的對象是以編程為中心的,是面向程序的對象。我們今天要講的OOD是面向信息的對象,是以用戶信息為中心的。
進一步閱讀:解讀面向對象的程序設計(二)
【編輯推薦】