面向?qū)ο蟮娜齻€基本特征和概念_第1頁
面向?qū)ο蟮娜齻€基本特征和概念_第2頁
面向?qū)ο蟮娜齻€基本特征和概念_第3頁
面向?qū)ο蟮娜齻€基本特征和概念_第4頁
面向?qū)ο蟮娜齻€基本特征和概念_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、面向?qū)ο蟮娜齻€基本特征(講解)面向?qū)ο蟮娜齻€基本特征是:封裝、繼承、多態(tài)。面向?qū)﹀杌咎卣鞣庋b封裝最好理解了。封裝是面向?qū)ο蟮奶卣髦?,是對象和類概念的主要特性。封裝,也就是把客觀事物封裝成抽象的類,并且類可以把自己的數(shù)據(jù)和方法只讓可信的類 或者對象操作,對不可信的進行信息隱藏。繼承面向?qū)ο缶幊?OOP)語言的一個主要功能就是“繼承”。繼承是指這樣一種能力:它可以 使用現(xiàn)有類的所有功能,并在無需重新編寫原來的類的情況下對這些功能進行擴展。通過繼承創(chuàng)建的新類稱為“子類”或“派生類”。被繼承的類稱為“基類”、“父類”或“超類”。繼承的過程,就是從一般到特殊的過程。要實現(xiàn)繼承,可以通過"繼

2、承"( Inheritance )和"組合"(Composition )來實現(xiàn)。在某些OOP語言中,一個子類可以繼承多個基類。但是一般情況下,一個子類只能有一個 基類,要實現(xiàn)多重繼承,可以通過多級繼承來實現(xiàn)。繼承概念的實現(xiàn)方式有三類:實現(xiàn)繼承、接口繼承和可視繼承。?實現(xiàn)繼承是指使用基類的屬性和方法而無需額外編碼的能力;?接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現(xiàn)的能力;?可視繼承是指子窗體(類)使用基窗體(類)的外觀和實現(xiàn)代碼的能力。在考慮使用繼承時,有一點需要注意,那就是兩個類之間的關(guān)系應(yīng)該是“屬于”關(guān)系。例如,Employee是一個人,Manag

3、er也是一個人,因此這兩個類都可以繼承Person 類。但是Leg類卻不能繼承Person 類,因為腿并不是一個人。抽象類僅定義將由子類創(chuàng)建的一般屬性和方法,創(chuàng)建抽象類時,請使用關(guān)鍵字Interface而不是Class。OO#發(fā)范式大致為:劃分對象抽象類-將類組織成為層次化結(jié)構(gòu)(繼承和合成)用類與實例進行設(shè)計和實現(xiàn)幾個階段。多態(tài)多態(tài)性(polymorphisn )是允許你將父對象設(shè)置成為和一個或更多的他的子對象相等的技 術(shù),賦值之后,父對象就可以根據(jù)當(dāng)前賦值給它的子對象的特性以不同的方式運作。簡單的說, 就是一句話:允許將子類類型的指針賦值給父類類型的指針。實現(xiàn)多態(tài),有二種方式,覆蓋,重載。覆

4、蓋,是指子類重新定義父類的虛函數(shù)的做法。重載,是指允許存在多個同名函數(shù),而這些函數(shù)的參數(shù)表不同(或許參數(shù)個數(shù)不同,或許 參數(shù)類型不同,或許兩者都不同)。其實,重載的概念并不屬于“面向?qū)ο缶幊獭保剌d的實現(xiàn)是:編譯器根據(jù)函數(shù)不同的參數(shù)表,對同名函數(shù)的名稱做修飾,然后這些同名函數(shù)就成了不同的函數(shù)(至少對于編譯器來說是這樣的)。如,有兩個同名函數(shù):function func(p:integer):integer;和 functionfunc(p:string):integer; 。那么編譯器做過修飾后的函數(shù)名稱可能是這樣的:int_func、str_func o對于這兩個函數(shù)的調(diào)用,在編譯器間就已經(jīng)

5、確定了,是靜態(tài)的(記?。菏庆o態(tài))。也 就是說,它們的地址在編譯期就綁定了(早綁定),因此,重載和多態(tài)無關(guān)!真正和多態(tài)相關(guān)的 是“覆蓋”。當(dāng)子類重新定義了父類的虛函數(shù)后,父類指針根據(jù)賦給它的不同的子類指針,動態(tài)(記?。菏莿討B(tài)!)的調(diào)用屬于子類的該函數(shù),這樣的函數(shù)調(diào)用在編譯期間是無法確定的(調(diào)用 的子類的虛函數(shù)的地址無法給出)。因此,這樣的函數(shù)地址是在運行期綁定的(晚邦定)。結(jié)論就是:重載只是一種語言特性,與多態(tài)無關(guān),與面向?qū)ο笠矡o關(guān)!引用一句Bruce Eckel的話:“不要犯傻,如果它不是晚邦定,它就不是多態(tài)?!蹦敲?,多態(tài)的作用是什么呢?我們知道,封裝可以隱藏實現(xiàn)細節(jié),使得代碼模塊化;繼承可以

6、擴展已存在的代碼模塊(類);它們的目的都是為了一一代碼重用。而多態(tài)則是為了實現(xiàn)另個目的一一接口重用!多態(tài)的作用,就是為了類在繼承和派生的時候,保證使用“家譜”中任 一類的實例的某一屬性時的正確調(diào)用。概念講解泛化(Generalization )圖表1泛化在上圖中,空心的三角表示繼承關(guān)系(類繼承),在UML的術(shù)語中,這種關(guān)系 被稱 為泛化(Generalization ) 。 Person(人)是 基類,Teacher( 教 師)、Student( 學(xué)生)、 Guest(來賓)是子類。若在邏輯上B是A的“一種”,并且 A的所有功能和屬性對B而言都有意義,則允許B繼承A的功能和屬性。例如,教 師是

7、人,Teacher 是Person 的"一種"(a kind of )。那么類 Teacher 可以從類Person派生(繼承)。如果A是基類,B是A的派生類,那么 B將繼承A的數(shù)據(jù)和函數(shù)。如果類A和類B毫不相關(guān),不可以為了使B的功能更多些而讓B繼承A的功能和屬性。若在邏輯上B是A的“一種" (a kind of ),則允許B繼承A的功能和屬性。聚合(組合)圖表2組合若在邏輯上 A是B的“一部分” (a part of ),則不允許 B從A派生,而是要用 A和其它 東西組合出Bo例如,眼(Eye)、鼻(Nose)、口 ( Mouth)、耳(Ear)是頭(Head)

8、的一部分,所以類 Head應(yīng)該由類Eye、Nose、Mouth、Ear組合而成,不是派生(繼承)而成。聚合的類型分為無、共享 (聚合)、復(fù)合(組合)三類。聚 合(aggregation ) o 圖表3共享上面圖中,有一個菱形(空心)表示聚合(aggregation )(聚合類型為共享), 聚合的意義表示has-a關(guān)系。聚合是一種相對松散的關(guān)系,聚合類B不需要對被聚 合的類A負責(zé)。組 合(composition )ChssAChs+ft-圖表4復(fù)合這幅圖與上面的唯一區(qū)別是菱形為實心的,它代表了 一種更為堅固的關(guān)系組 合(composition )(聚合類型為復(fù)合)。組 合表示的關(guān)系也是has-a

9、 ,不過在這里, A的生命期受B控制。即A會隨著B的創(chuàng)建而創(chuàng)建,隨B的消亡而消亡。依 賴(Dependency)圖表5依賴這里B與A的關(guān)系只是一種依賴(Dependency) 關(guān)系,這種關(guān)系表明,如果類被修改, 那么類B會受到影響。什么是面向?qū)ο?,和面向過程的區(qū)別是什么最佳答案面向過程就是分析出解決問題所需要的步驟,然后用函數(shù)把這些步驟一步一步實現(xiàn),使用的時候一個一個依次調(diào)用就可以了。面向?qū)ο笫前褬?gòu)成問題事務(wù)分解成各個對象,建立對象的目的不是為了完成一個步驟,而是為了描敘某個事物在整個解決問題的步驟中的行為。例如五子棋,面向過程的設(shè)計思路就是首先分析問題的步驟: 1、開始游戲, 2 、黑子先走

10、, 3 、繪制畫面, 4 、判斷輸贏,5 、輪到白子,6 、繪制畫面,7 、判斷輸贏, 8 、 返回步驟 2 , 9 、 輸出最后結(jié)果。 把上面每個步驟用分別的函數(shù)來實現(xiàn),問題就解決了。而面向?qū)ο蟮脑O(shè)計則是從另外的思路來解決問題。 整個五子棋可以分為 1 、 黑白雙方,這兩方的行為是一模一樣的, 2 、棋盤系統(tǒng),負責(zé)繪制畫面, 3 、規(guī)則系統(tǒng),負責(zé)判定諸如犯規(guī)、輸贏等。第一類對象(玩家對象)負責(zé)接受用戶輸入,并告知第二類對象(棋盤對象)棋子布局的變化,棋盤對象接收到了棋子的 i 變化就要負責(zé)在屏幕上面顯示出這種變化, 同時利用第三類對象 (規(guī)則系統(tǒng)) 來對棋局進行判定??梢悦黠@地看出, 面向?qū)?/p>

11、象是以功能來劃分問題, 而不是步驟。 同樣是繪制棋局,這樣的行為在面向過程的設(shè)計中分散在了總多步驟中, 很可能出現(xiàn)不同的繪制版本, 因為通常設(shè)計人員會考慮到實際情況進行各種各樣的簡化。 而面向?qū)ο蟮脑O(shè)計中,繪圖只可能在棋盤對象中出現(xiàn),從而保證了繪圖的統(tǒng)一。功能上的統(tǒng)一保證了面向?qū)ο笤O(shè)計的可擴展性。 比如我要加入悔棋的功能, 如果要改動面向過程的設(shè)計, 那么從輸入到判斷到顯示這一連串的步驟都要改動, 甚至步驟之間的循序都要進行大規(guī)模調(diào)整。 如果是面向?qū)ο蟮脑挘?只用改動棋盤對象就行了, 棋盤系統(tǒng)保存了黑白雙方的棋譜, 簡單回溯就可以了, 而顯示和規(guī)則判斷則不用顧及, 同時整個對對象功能的調(diào)用順序

12、都沒有變化, 改動只是局部的。再比如我要把這個五子棋游戲改為圍棋游戲, 如果你是面向過程設(shè)計, 那么五子棋的規(guī)則就分布在了你的程序的每一個角落, 要改動還不如重寫。 但是如果你當(dāng)初就是面向?qū)ο蟮脑O(shè)計, 那么你只用改動規(guī)則對象就可以了, 五子棋和圍棋的區(qū)別不就是規(guī)則嗎?(當(dāng)然棋盤大小好像也不一樣,但是你會覺得這是一個難題嗎?直接在棋盤對象中進行一番小改動就可以了。 ) 而下棋的大致步驟從面向?qū)ο蟮慕嵌葋砜礇]有任何變化。當(dāng)然, 要達到改動只是局部的需要設(shè)計的人有足夠的經(jīng)驗, 使用對象不能保證你的程序就是面向?qū)ο螅?初學(xué)者或者很蹩腳的程序員很可能以面向?qū)ο笾摱忻嫦蜻^程之實, 這樣設(shè)計出來的所謂面

13、向?qū)ο蟮某绦蚝茈y有良好的可移植性和可擴展性。111111111111111111111111111111111111111111111111111111111111111111111111111111一、 什么是遞歸很多 數(shù)據(jù)結(jié)構(gòu) 的定義都是根據(jù)遞歸性質(zhì)來進行定義的, 是因為這些結(jié)構(gòu)固有的性質(zhì)。遞歸是指某個 函數(shù) 直接或間接的調(diào)用自身。問題的求解過程就是劃分成許多相同性質(zhì)的子問題的求解,而小問題的求解過程可以很容易的求出,這些子問題的解就構(gòu)成里原問題的解了。二、遞歸的幾個特點1 . 遞歸式,就是如何將原問題劃分成子問題。2 .遞歸出口,遞歸終止的條件,即最小子問題的求解,可以允許多個出口。3

14、.界函數(shù),問題規(guī)模變化的 函數(shù) ,它保證遞歸的規(guī)模向出口條件靠攏三、遞歸的運做機制很明顯,很多問題本身固有的性質(zhì)就決定此類問題是遞歸定義,所以遞歸程序很直接算法程序結(jié)構(gòu)清晰、思路明了。但是遞歸的執(zhí)行過程卻很讓人費解,這也是讓很多人難理解遞歸的原因之一。由于遞歸調(diào)用是對 函數(shù) 自身的調(diào)用,在一次調(diào)用沒有結(jié)束之前又開始了另外一次調(diào)用,按照作用域的規(guī)定, 函數(shù) 在執(zhí)行終止之前是不能收回所占用的空間,必須保存下來,這也就意味著每一次的調(diào)用都要把分配的相應(yīng)空間保存起來。為了更好管理這些空間,系統(tǒng)內(nèi)部設(shè)置一個棧,用于存放每次 函數(shù) 調(diào)用與返回所需的各種數(shù)據(jù),其中主要包括 函數(shù) 的調(diào)用結(jié)束的返回地址,返回值

15、,參數(shù)和局部變量等。其過程大致如下:1 . 計算當(dāng)前 函數(shù)的實參的值2 .分配空間,并將首地址壓棧,保護現(xiàn)場3 .轉(zhuǎn)到函數(shù) 體,執(zhí)行各語句,此前部分會重復(fù)發(fā)生(遞歸調(diào)用)4 .直到出口,從棧頂取出相應(yīng)數(shù)據(jù),包括,返回地址,返回值等等,收回空間,恢復(fù)現(xiàn)場,轉(zhuǎn)到上一層的調(diào)用位置繼續(xù)執(zhí)行本次調(diào)用未完成的語句。四、引入非遞歸從用戶使用角度來說, 遞歸真的很簡便, 對程序宏觀上容易理解。 遞歸程序的時間復(fù)雜度雖然可以根據(jù)T(n尸T(n-1)*f(n)遞歸求出,其中f(n)是遞歸式的執(zhí)行時間復(fù)雜度,一般來說,時間復(fù)雜度和對應(yīng)的非遞歸差不多, 但是遞歸的效率是相當(dāng)?shù)偷乃饕l(fā)費在反復(fù)的進棧出棧, 各種中斷等

16、機制上(具體的可以參考 操作系統(tǒng) )更有甚者,在遞歸求解過程中, 某些解會重復(fù)的求好幾次,這是不能容忍的,這些也是引入非遞歸機制的原因之一。五、遞歸轉(zhuǎn)非遞歸的兩種方法1. 一般根據(jù)是否需要回朔可以把遞歸分成簡單遞歸和復(fù)雜遞歸, 簡單遞歸一般就是根據(jù)遞歸式來找出遞推公式(這也就引申出分治思想和動態(tài)規(guī)劃) 。而復(fù)雜遞歸一般就是模擬系統(tǒng)處理遞歸的機制,使用?;蜿犃械?數(shù)據(jù)結(jié)構(gòu) 保存回朔點來求解。六、幾個簡單的例子1 . 求解階乘階乘的定義就是n!=n*(n-1)! 0!=1 1!=1根據(jù)定義我們很容易就想到遞歸方法,做法如下int Fact(int n)if(n=0) return 1; / 遞歸出

17、口return n*Fact(n-1) /n*Fact(n-1) 就是遞歸式,其中 n-1 就是界 函數(shù)2 .再看 Fibonacci 的例子定義:某項的值等于前兩項的和,其中第一和第二項為 1 。根據(jù)定義我們很容易寫出程序,這里就不寫出來了,當(dāng)我們用筆劃幾下的時候我們是否會發(fā)現(xiàn)有很多解是重復(fù)求出的。舉個例子要求F(5)F(5)=F(4)+F(3);F(4)=F(3)+F(2);F(3)=F(2)+F(1);其中F(3)求解2次。這顯然就是時間的浪費。下面我們用遞推技術(shù)來轉(zhuǎn)化成非遞歸從例子可以發(fā)現(xiàn)我們可以倒過來求解,即從底到頂把F(n)之前要計算的東西保存下來。程序就是:int Fibona(int n)int p1=1,p2=1;/int a100=0;/a1=1,a2=1;for(int i=3;i<=n;i+)/從三開始就可以了,后面的 return 包括 1, 2 兩種情況int r=p1;/遞推,可以使用數(shù)組全部保存p1=p2;p2+=r;/a =ai-1+ai-2return p2;/return an;3 .帶回朔的復(fù)雜遞歸:具體例子參照二叉樹的遍歷程序。url= /url舉個簡單點的:求解按照中點優(yōu)先的順序遍歷線形表按照定義,當(dāng)然是想到先輸出求解的線形表中點值,再輸出左部分,然后右部分。部分代碼如下:void Mid_O

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論