面向过程 VS 面向对象
面向過程(Process Oriented)這個詞是在面向對象(Object Oriented)出現之后為與之相對而提出的。其實它在以前基本被叫做“結構化編程”。
???????早期的程序設計,大量使用共享變量(全局變量)和GOTO語句一類的東西,后來有人證明所有有意義的程序流程都可以使用三種基本流程(順序、選擇、重復)來實現,并提出“GOTO有害說”,從此人們進行編程的方式發生重大變化,每種語言都提供這些基本控制結構的實現方式,并提供把數據訪問局部化的能力,以及某種形式的模塊化/分別編譯機制。在這些基礎上,人們所進行的編程活動基本是通過寫用于不同目的的功能函數/過程來實現,故稱為“面向過程”。
?????
????? ? 面向過程開發方式是對計算機底層結構的一層抽象,它明顯把程序的內容分為數據和操縱數據的操作兩部分。這種編程方式的核心問題是數據結構和算法的開發和優化。C 語言所提供的機制就是典型的結構化編程設施。
???????面向對象是繼結構化革命之后的又一次軟件開發方式革命。面向對象的主要思想是基于抽象數據類型的(Abstract Data Type, ADT):在結構化編程過程中,人們發現把某種數據結構和用于操縱它的各種操作以某種模塊化方式綁定到一起會非常方便,使用這種方式進行編程時數據結構的接口是固定的。
???? 如果對抽象數據類型進一步抽象,就會發現把這種數據類型的實例當作一個具體的東西、事物、對象,就可以引發人們對編程過程中怎樣看待所處理的問題的一次大的改變。抽象數據類型方法雖然也有一定的抽象能力,但其核心仍然是數據結構和算法。而面向對象方法直接把所有事物都當作獨立的對象,處理問題過程中所思考的不再主要是怎樣用數據結構來描述問題,而是直接考慮重現問題中各個對象之間的關系。可以說,面向對象革命的最重要價值就在于改變了人們看待和處理問題的方式。
???? 面向對象方法中,對象可以接受其他對象傳來的消息,也可以向其他對象發送消息。有的語言靜態類型,決定了對象可接受的消息的范圍,這稱為對象的類型的接口。有的語言中對象可以接受任何消息,但只對其有意義的消息進行反應。對象中可以包含其他對象,這成為“聚合”,對象可以被當作其他類型的對象,這要求對象的類型“繼承”另外的類型。對象只能通過其所提供的接口來進行訪問,其內部具體實現是不可訪問的,這成為“封裝”。面向對象方法的三個核心要素是:封裝、繼承、多態。
??
? ? C和C++都可以進行面向過程和面向對象的編程,不同的是C++對面向對象直接提供語言支持,而C中只能通過傳統方式手動操作對象來模擬對象行為。C++是多模式、多范式的編程語言,它還可以進行泛型編程。
???
????Java是一門面向對象的語言,那對面向對象和面向過程不是很清楚的請看看下面的內容,說不定對你有幫助:
????面向過程就是分析出解決問題所需要的步驟,然后用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就可以了。
????面向對象是把構成問題事務分解成各個對象,建立對象的目的不是為了完成一個步驟,而是為了描敘某個事物在整個解決問題的步驟中的行為。
?
例如五子棋:
面向過程的設計思路就是首先分析問題的步驟:
1、開始游戲,
2、黑子先走,
3、繪制畫面,
4、判斷輸贏,
5、輪到白子,
6、繪制畫面,
7、判斷輸贏,
8、返回步驟2,
9、輸出最后結果。
把上面每個步驟用分別的函數來實現,問題就解決了。
?
面向對象的設計則是從另外的思路來解決問題。整個五子棋可以分為:
1、黑白雙方,這兩方的行為是一模一樣的,
2、棋盤系統,負責繪制畫面,
3、規則系統,負責判定諸如犯規、輸贏等。
??????? 第一類對象(玩家對象)負責接受用戶輸入,并告知第二類對象(棋盤對象)棋子布局的變化,棋盤對象接收到了棋子的變化就要負責在屏幕上面顯示出這種變化,同時利用第三類對象(規則系統)來對棋局進行判定。
?????? 可以明顯地看出,面向對象是以功能來劃分問題,而不是步驟。同樣是繪制棋局,這樣的行為在面向過程的設計中分散在了總多步驟中,很可能出現不同的繪制版本,因為通常設計人員會考慮到實際情況進行各種各樣的簡化。而面向對象的設計中,繪圖只可能在棋盤對象中出現,從而保證了繪圖的統一。
???? 功能上的統一保證了面向對象設計的可擴展性。比如我要加入悔棋的功能,如果要改動面向過程的設計,那么從輸入到判斷到顯示這一連串的步驟都要改動,甚至步驟之間的循序都要進行大規模調整。如果是面向對象的話,只用改動棋盤對象就行了,棋盤系統保存了黑白雙方的棋譜,簡單回溯就可以了,而顯示和規則判斷則不用顧及,同時整個對對象功能的調用順序都沒有變化,改動只是局部的。
到這里就可以很明顯的看出面向對象和面向過程的區別所在了。
?
總結:
1.面向過程程序設計方法的實質上是從計算機處理問題的觀點來進行程序設計工作:輸入——運算——輸出。面向過程程序設計者需要變更習慣的思維方法以貼近計算機的內部工作機理。面向過程程序設計所具有的流的工作性質,試圖通過信息流及其轉換來認識系統,不僅加大了程序設計的難度,同時亦使得程序的可理解性比較差。
面向過程程序設計方法中,一種普遍采用的優化方法是使用結構化的程序設計方法。
面向過程程序設計方法一般適宜采用自上而下的設計方法。
面向過程程序設計方法需要在一開始就全面的,自上而下的設計整個應用程序的架構,因此要求程序設計者對問題域有全面的了解。
面向過程程序設計方法很難復用以前已經設計完成的軟件。
2.面向對象程序設計是一種自下而上的程序設計方法,往往從問題的一部分著手,一點一點地構建出整個程序。面向對象設計一數據為中心,類作為表現數據的工具,成為劃分程序的基本單位。
面向對象有以下幾個重要特點:
(1)客觀世界有對象組成
(2)對象抽象為類
(3)類與類之間存在繼承關系
(4)對象之間通過傳遞消息而彼此聯系
面向對象是一種思想,符合人們的思考習慣。面向對象的出現,讓復雜的問題簡單化。面向對象的出現,讓曾經的執行者,變成了現在的指揮者。
?
附:
下面簡單介紹面向對象三大特征:
封裝:
封裝是指將數據與具體操作的實現代碼放在某個對象內部,使這些代碼的實現細節不被外界發現,外界只能通過接口使用該對象,而不能通過任何形式修改對象內部實現,正是由于封裝機制,程序在使用某一對象時不需要關心該對象的數據結構細節及實現操作的方法。使用封裝能隱藏對象實現細節,使代碼更易維護,同時因為不能直接調用、修改對象內部的私有信息,在一定程度上保證了系統安全性。
繼承:
繼承來源于現實世界,一個最簡單的例子就是孩子會具有父母的一些特征,即每個孩子都會繼承父親或者母親的某些特征,當然這只是最基本的繼承關系,現實世界中還存在著更復雜的繼承,面向對象之所以使用繼承機制主要是用于實現代碼的復用多個類所公用的代碼部分可以只在一個類中提供,而其他類只需要繼承即可。
多態:
多態與繼承纖細緊密,是面向對象編程中另一個突出的特征,所謂的多態是指在繼承體系中,所有派生類都從基類繼承接口,但由于每個派生類都是獨立的實體,因此在接收同一消息的時候,可能會生成不同的響應。多態的作用作為隱藏代碼實現細節,使得代碼能夠模塊化;擴展代碼模塊,實現接口重用。簡單來說:一種行為產生多種效果。
總的來說:封裝可以隱藏實現細節同時包含私有成員,使得代碼模塊化并增加安全指數;基礎可以擴展已存在的模塊,目的是為了代碼重用;多態則是為了保證:類在繼承和派生的時候,保證家譜中任何類的實例被正確調用,實現了接口重用。
多態實現:
實現多態,有二種方式,覆蓋,重載。
覆蓋,是指子類重新定義父類的虛函數的做法。
重載,是指允許存在多個同名函數,而這些函數的參數表不同(或許參數個數不同,或許參數類型不同,或許兩者都不同)。
其實,重載的概念并不屬于“面向對象編程”,重載的實現是:編譯器根據函數不同的參數表,對同名函數的名稱做修飾,然后這些同名函數就成了不同的函數(至少對于編譯器來說是這樣的)。如,有兩個同名函數:function func(p:integer):integer;和function func(p:string):integer;。那么編譯器做過修飾后的函數名稱可能是這樣的:int_func、str_func。對于這兩個函數的調用,在編譯器間就已經確定了,是靜態的(記住:是靜態)。也就是說,它們的地址在編譯期就綁定了(早綁定),因此,重載和多態無關!真正和多態相關的是“覆蓋”。當子類重新定義了父類的虛函數后,父類指針根據賦給它的不同的子類指針,動態(記住:是動態!)的調用屬于子類的該函數,這樣的函數調用在編譯期間是無法確定的(調用的子類的虛函數的地址無法給出)。因此,這樣的函數地址是在運行期綁定的(晚綁定)。結論就是:重載只是一種語言特性,與多態無關,與面向對象也無關。
?
扯到覆蓋和重載了,那就說說函數重載、覆蓋、隱藏的基本定義吧。
函數重載:是指允許存在多個同名函數,這些函數的參數列表不同,或許是參數個數不同,或許是參數類型不同,或許是兩者都不同。重要一點:函數重載是發生在同一個類中。調用時,根據參數類型的不同進行調用,同時編譯器在編譯期間就確定了要調用的函數。(函數的重載與多態無關)。
函數覆蓋:函數覆蓋也被稱為函數重寫(override),是子類重新定義基類虛函數的方法。
構成函數覆蓋的條件:
(1)基類的函數必須是虛函數(virtual進行聲明)
(2)發生覆蓋的兩個函數必須分別位于派生類和基類中
(3)函數名稱和參數列表必須完全相同
由于c++,c#多態性是通過虛函數來實現的,所以函數覆蓋總是和多態聯系在一起,并且是程序在運行時才確定要調用的函數,因此也成為動態綁定或者后期綁定。
?
函數隱藏:指子類中具有和基類同名的函數,但是并不考慮參數列表是否相同,從而在子類中隱藏了基類的同名函數。有以下兩種情況:
(1)子類函數和基類函數完全相同,只是基類的函數沒有使用virtual關鍵字,此時基類的函數將被隱藏。
(2)子類函數和基類函數名字相同,但是參數列表不同,在這種情況下,無論基類的函數是否聲明為virtual,基類的函數都將被隱藏。
總結
以上是生活随笔為你收集整理的面向过程 VS 面向对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电磁兼容(EMC)标准结构的划分与分类
- 下一篇: pytest配置文件pytest.ini