一. 面向?qū)ο缶幊?/h1>
面向?qū)ο缶幊蹋ㄓ⒄Z(yǔ):Object-oriented programming,縮寫(xiě):OOP)是種具有對(duì)象概念的程序編程典范,同時(shí)也是一種程序開(kāi)發(fā)的抽象方針侦啸。它將對(duì)象作為程序的基本單元腌且,將程序和數(shù)據(jù)封裝其中,以提高軟件的重用性姐叁、靈活性和擴(kuò)展性,對(duì)象里的程序可以訪問(wèn)及經(jīng)常修改對(duì)象相關(guān)聯(lián)的數(shù)據(jù)洗显。在面向?qū)ο蟪绦蚓幊汤锿馇保?jì)算機(jī)程序會(huì)被設(shè)計(jì)成彼此相關(guān)的對(duì)象。
面向?qū)ο蟪绦蚓幊痰亩x是使用“對(duì)象”來(lái)做設(shè)計(jì)挠唆,但并非所有的編程語(yǔ)言都直接支持“面向?qū)ο蟪绦蚓幊獭毕嚓P(guān)技術(shù)與結(jié)構(gòu)处窥。通常,OOP被理解為一種將程序分解為封裝數(shù)據(jù)及相關(guān)操作的模塊而進(jìn)行的編程方式玄组。有別于其它編程方式滔驾,OOP中的與某數(shù)據(jù)類(lèi)型相關(guān)的一系列操作都被有機(jī)地封裝到該數(shù)據(jù)類(lèi)型當(dāng)中,而非散放于其外俄讹,因而OOP中的數(shù)據(jù)類(lèi)型不僅有著狀態(tài)哆致,還有著相關(guān)的行為。
這就是面向?qū)ο蟮乃季S特點(diǎn)患膛,抽象有用的屬性和行為封裝成一個(gè)類(lèi)摊阀。這個(gè)過(guò)程中你也許會(huì)發(fā)現(xiàn)很多屬性或方法是和另一個(gè)類(lèi)相同的,那么你就可以采用繼承的方式避免重復(fù)(當(dāng)然這個(gè)過(guò)程也有可能是,當(dāng)你設(shè)計(jì)完一個(gè)個(gè)類(lèi)后胞此,才發(fā)現(xiàn)他們有共同點(diǎn)臣咖,然后再抽取出基類(lèi))。更重要的是豌鹤,繼承是可以不原樣照搬的亡哄,我們可以通過(guò)重寫(xiě)實(shí)現(xiàn)相同行為或?qū)傩缘奶赜袑?shí)現(xiàn)方式,這種特點(diǎn)稱(chēng)之為多態(tài),從此得出面向?qū)ο蟮娜齻€(gè)基本特征:
封裝布疙、繼承蚊惯、多態(tài)
1.1 類(lèi)與對(duì)象
面對(duì)對(duì)象編程,核心是對(duì)象灵临,那么對(duì)象是什么呢截型?對(duì)象指的是類(lèi)的實(shí)例。
1.1.1 類(lèi)的定義
類(lèi)的定義就是一個(gè)模板儒溉,它描述的一類(lèi)對(duì)象的屬性與行為宦焦。類(lèi)往往是抽象的、沒(méi)有實(shí)體的顿涣。類(lèi)的定義包含了數(shù)據(jù)的形式以及對(duì)數(shù)據(jù)的操作波闹。舉例來(lái)說(shuō):哺乳動(dòng)物類(lèi),是抽象的這個(gè)類(lèi)會(huì)包含哺乳動(dòng)物的一切基礎(chǔ)特征涛碑,即所有“哺乳動(dòng)物”都共有的特征或行為精堕,現(xiàn)實(shí)中沒(méi)有哺乳動(dòng)物這一實(shí)體,只有老虎蒲障,獅子等歹篓。編程工作中套用這一思維模式,我們將程序中的實(shí)例的共同屬性或方法抽象為類(lèi)揉阎,例如一個(gè)系統(tǒng)中的用戶(hù)有張三庄撮、李四我們會(huì)把他們抽象為Person類(lèi),或者稱(chēng)之為一個(gè)名為Person的數(shù)據(jù)類(lèi)型毙籽,而張三洞斯、李四則是我們具體的實(shí)體。
1.1.2 對(duì)象的定義
對(duì)象指的是類(lèi)的實(shí)例坑赡,就是內(nèi)含數(shù)據(jù)和數(shù)據(jù)的處理方法的模塊巡扇。對(duì)象則是根據(jù)所屬類(lèi)模板創(chuàng)造出來(lái)的實(shí)實(shí)在在的事物。在程序中我將這個(gè)實(shí)實(shí)在在的事物稱(chēng)之為實(shí)例垮衷,我們?yōu)樗膶傩再x上特定的值,讓它成為張三或者李四乖坠。在內(nèi)存里來(lái)說(shuō)搀突,對(duì)象是表示的就是具體數(shù)據(jù)。
1.1.3 對(duì)比類(lèi)與對(duì)象
系統(tǒng)給對(duì)象分配內(nèi)存空間熊泵,而不會(huì)給類(lèi)分配內(nèi)存空間仰迁。這很好理解甸昏,類(lèi)是抽象的,系統(tǒng)不可能給抽象的東西分配空間徐许,而對(duì)象則是具體的施蜜。
二. 面向?qū)ο蟮娜蠡咎卣?/h1>
2.1 封裝
封裝是面向?qū)ο蟮奶卣髦唬菍?duì)象和類(lèi)概念的主要特性雌隅。封裝翻默,也就是把客觀事物封裝成抽象的類(lèi),并且類(lèi)可以把自己的數(shù)據(jù)和方法只讓可信的類(lèi)或者對(duì)象操作恰起,對(duì)不可信的進(jìn)行信息隱藏修械,而它們通常利用接口實(shí)現(xiàn)消息的傳入傳出。通常來(lái)說(shuō)检盼,成員的訪問(wèn)權(quán)限被分為4種:公有成員肯污、私有成員、默認(rèn)成員以及保護(hù)成員吨枉。
2.2 繼承
面向?qū)ο缶幊?(OOP) 語(yǔ)言的一個(gè)主要功能就是“繼承”蹦渣。繼承是指:它可以使用現(xiàn)有類(lèi)的所有功能,并在無(wú)需重新編寫(xiě)原來(lái)的類(lèi)的情況下對(duì)這些功能進(jìn)行擴(kuò)展貌亭。
通過(guò)繼承創(chuàng)建的新類(lèi)稱(chēng)為“子類(lèi)”或“派生類(lèi)”柬唯。
被繼承的類(lèi)稱(chēng)為“基類(lèi)”、“父類(lèi)”或“超類(lèi)”属提。
繼承的過(guò)程权逗,就是從一般到特殊的過(guò)程。
要實(shí)現(xiàn)繼承冤议,可以通過(guò)“繼承”(Inheritance)和“組合”(Composition)來(lái)實(shí)現(xiàn)斟薇。
在某些 OOP 語(yǔ)言中,一個(gè)子類(lèi)可以繼承多個(gè)基類(lèi)恕酸。但是一般情況下堪滨,一個(gè)子類(lèi)只能有一個(gè)基類(lèi)(如Java語(yǔ)言),要實(shí)現(xiàn)多重繼承蕊温,可以通過(guò)多級(jí)繼承來(lái)實(shí)現(xiàn)袱箱。
繼承概念的實(shí)現(xiàn)方式有三類(lèi):實(shí)現(xiàn)繼承、接口繼承和可視繼承义矛。
? 實(shí)現(xiàn)繼承是指使用基類(lèi)的屬性和方法而無(wú)需額外編碼的能力发笔;
?接口繼承是指僅使用屬性和方法的名稱(chēng)、但是子類(lèi)必須提供實(shí)現(xiàn)的能力凉翻;
? 可視繼承是指子窗體(類(lèi))使用基窗體(類(lèi))的外觀和實(shí)現(xiàn)代碼的能力了讨。
在考慮使用繼承時(shí),有一點(diǎn)需要注意,那就是兩個(gè)類(lèi)之間的關(guān)系應(yīng)該是“屬于”關(guān)系前计。例如胞谭,Employee 是一個(gè)人,Manager 也是一個(gè)人男杈,因此這兩個(gè)類(lèi)都可以繼承 Person 類(lèi)丈屹。但是 Leg 類(lèi)卻不能繼承 Person 類(lèi),因?yàn)橥炔⒉皇且粋€(gè)人伶棒。
2.3 多態(tài)
多態(tài) (面向?qū)ο缶幊?")(Polymorphism)是指由繼承而產(chǎn)生的相關(guān)的不同的類(lèi)旺垒,其對(duì)象對(duì)同一消息會(huì)做出不同的響應(yīng)。具體程序中苞冯,是允許你將父類(lèi)的引用設(shè)置成為他的子類(lèi)的對(duì)象的技術(shù)袖牙,當(dāng)父類(lèi)引用調(diào)用相應(yīng)的行為會(huì)根據(jù)賦值給他的子類(lèi)對(duì)象的特性行為方式運(yùn)作。簡(jiǎn)單一句話:允許將子類(lèi)類(lèi)型的指針賦值給父類(lèi)類(lèi)型的指針舅锄。
實(shí)現(xiàn)多態(tài)鞭达,有二種方式:覆蓋(重寫(xiě)),重載皇忿。
覆蓋畴蹭,是指子類(lèi)重新定義父類(lèi)的虛函數(shù)的做法。
重載鳍烁,是指允許存在多個(gè)同名函數(shù)叨襟,而這些函數(shù)的參數(shù)表不同(或許參數(shù)個(gè)數(shù)不同,或許參數(shù)類(lèi)型不同幔荒,或許兩者都不同)糊闽。
其實(shí),重載的概念并不屬于“面向?qū)ο缶幊獭钡海剌d的實(shí)現(xiàn)是:編譯器根據(jù)函數(shù)不同的參數(shù)表右犹,對(duì)同名函數(shù)的名稱(chēng)做修飾,然后這些同名函數(shù)就成了不同的函數(shù)(至少對(duì)于編譯器來(lái)說(shuō)是這樣的)姚垃。如念链,有兩個(gè)同名函數(shù):function func(p:integer):integer;和function func(p:string):integer;。那么編譯器做過(guò)修飾后的函數(shù)名稱(chēng)可能是這樣的:int_func积糯、str_func掂墓。對(duì)于這兩個(gè)函數(shù)的調(diào)用,在編譯器間就已經(jīng)確定了看成,是靜態(tài)的(記拙唷:是靜態(tài))。也就是說(shuō)川慌,它們的地址在編譯期就綁定了(早綁定)啦粹,因此偿荷,重載和多態(tài)無(wú)關(guān)!真正和多態(tài)相關(guān)的是“覆蓋”唠椭。當(dāng)子類(lèi)重新定義了父類(lèi)的虛函數(shù)后,父類(lèi)指針根據(jù)賦給它的不同的子類(lèi)指針忍饰,動(dòng)態(tài)(記滋吧:是動(dòng)態(tài)!)的調(diào)用屬于子類(lèi)的該函數(shù)艾蓝,這樣的函數(shù)調(diào)用在編譯期間是無(wú)法確定的(調(diào)用的子類(lèi)的虛函數(shù)的地址無(wú)法給出)力崇。因此,這樣的函數(shù)地址是在運(yùn)行期綁定的(晚邦定)赢织。結(jié)論就是:重載只是一種語(yǔ)言特性亮靴,與多態(tài)無(wú)關(guān),與面向?qū)ο笠矡o(wú)關(guān)于置!引用一句Bruce Eckel的話:“不要犯傻茧吊,如果它不是晚邦定,它就不是多態(tài)八毯〈曛叮”
那么,多態(tài)的作用是什么呢话速?
我們知道讶踪,封裝可以隱藏實(shí)現(xiàn)細(xì)節(jié),使得代碼模塊化泊交;繼承可以擴(kuò)展已存在的代碼模塊(類(lèi))乳讥;它們的目的都是為了——代碼重用。而多態(tài)則是為了實(shí)現(xiàn)另一個(gè)目的——接口重用廓俭!多態(tài)的作用云石,就是為了類(lèi)在繼承和派生的時(shí)候,保證使用“家譜”中任一類(lèi)的實(shí)例的某一屬性時(shí)的正確調(diào)用白指。
三. 面向?qū)ο笈c面向過(guò)程編程的概述
面向?qū)ο蟪绦蛟O(shè)計(jì)可以看作一種在程序中包含各種獨(dú)立而又互相調(diào)用的對(duì)象的思想留晚,這與傳統(tǒng)的思想剛好相反:傳統(tǒng)的程序設(shè)計(jì)主張將程序看作一系列函數(shù)的集合,或者直接就是一系列對(duì)計(jì)算機(jī)下達(dá)的指令告嘲。面向?qū)ο蟪绦蛟O(shè)計(jì)中的每一個(gè)對(duì)象都應(yīng)該能夠接受數(shù)據(jù)错维、處理數(shù)據(jù)并將數(shù)據(jù)傳達(dá)給其它對(duì)象,因此它們都可以被看作一個(gè)小型的“機(jī)器”橄唬,即對(duì)象赋焕。目前已經(jīng)被證實(shí)的是,面向?qū)ο蟪绦蛟O(shè)計(jì)推廣了程序的靈活性和可維護(hù)性,并且在大型項(xiàng)目設(shè)計(jì)中廣為應(yīng)用肪笋。此外,支持者聲稱(chēng)面向?qū)ο蟪绦蛟O(shè)計(jì)要比以往的做法更加便于學(xué)習(xí)呆细,因?yàn)樗軌蜃屓藗兏?jiǎn)單地設(shè)計(jì)并維護(hù)程序侨嘀,使得程序更加便于分析臭挽、設(shè)計(jì)、理解咬腕。反對(duì)者在某些領(lǐng)域?qū)Υ擞枰苑裾J(rèn)欢峰。
當(dāng)我們提到面向?qū)ο蟮臅r(shí)候,它不僅指一種程序設(shè)計(jì)方法涨共。它更多意義上是一種程序開(kāi)發(fā)方式纽帖。在這一方面,我們必須了解更多關(guān)于面向?qū)ο笙到y(tǒng)分析和面向?qū)ο笤O(shè)計(jì)(Object Oriented Design举反,簡(jiǎn)稱(chēng)OOD)方面的知識(shí)懊直。許多流行的編程語(yǔ)言是面向?qū)ο蟮?它們的風(fēng)格就是會(huì)透由對(duì)象來(lái)創(chuàng)出實(shí)例。