轉 物件導向的三個基本特徵

來源:互聯網
上載者:User

標籤:des   style   blog   http   io   ar   color   os   使用   

物件導向的三個基本特徵是:封裝、繼承、多態。封裝封裝最好理解了。封裝是物件導向的特徵之一,是對象和類概念的主要特性。封裝,也就是把客觀事物封裝成抽象的類,並且類可以把自己的資料和方法只讓可信的類或者對象操作,對不可信的進行資訊隱藏。繼承物件導向編程 (OOP) 語言的一個主要功能就是“繼承”。繼承是指這樣一種能力:它可以使用現有類的所有功能,並在無需重新編寫原來的類的情況下對這些功能進行擴充。通過繼承建立的新類稱為“子類”或“衍生類別”。被繼承的類稱為“基類”、“父類”或“超類”。繼承的過程,就是從一般到特殊的過程。要實現繼承,可以通過“繼承”(Inheritance)和“組合”(Composition)來實現。在某些 OOP 語言中,一個子類可以繼承多個基類。但是一般情況下,一個子類只能有一個基類,要實現多重繼承,可以通過多級繼承來實現。 繼承概念的實現方式有三類:實現繼承、介面繼承和可視繼承。Ø         實現繼承是指使用基類的屬性和方法而無需額外編碼的能力;Ø         介面繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現的能力;Ø         可視繼承是指子表單(類)使用基表單(類)的外觀和實現代碼的能力。在考慮使用繼承時,有一點需要注意,那就是兩個類之間的關係應該是“屬於”關係。例如,Employee 是一個人,Manager 也是一個人,因此這兩個類都可以繼承 Person 類。但是 Leg 類卻不能繼承 Person 類,因為腿並不是一個人。抽象類別僅定義將由子類建立的一般屬性和方法,建立抽象類別時,請使用關鍵字 Interface 而不是 Class。OO開發範式大致為:劃分對象→抽象類別→將類組織成為層次化結構(繼承和合成) →用類與執行個體進行設計和實現幾個階段。 多態多態性(polymorphisn)是允許你將父物件設定成為和一個或更多的他的子物件相等的技術,賦值之後,父物件就可以根據當前賦值給它的子物件的特性以不同的方式運作。簡單的說,就是一句話:允許將子類類型的指標賦值給父類類型的指標。實現多態,有二種方式,覆蓋,重載。覆蓋,是指子類重新定義父類的虛函數的做法。重載,是指允許存在多個同名函數,而這些函數的參數表不同(或許參數個數不同,或許參數類型不同,或許兩者都不同)。其實,重載的概念並不屬於“物件導向編程”,重載的實現是:編譯器根據函數不同的參數表,對同名函數的名稱做修飾,然後這些同名函數就成了不同的函數(至少對於編譯器來說是這樣的)。如,有兩個同名函數:function func(p:integer):integer;和function func(p:string):integer;。那麼編譯器做過修飾後的函數名稱可能是這樣的:int_func、str_func。對於這兩個函數的調用,在編譯器間就已經確定了,是靜態(記住:是靜態)。也就是說,它們的地址在編譯期就綁定了(早綁定),因此,重載和多態無關!真正和多態相關的是“覆蓋”。當子類重新定義了父類的虛函數後,父類指標根據賦給它的不同的子類指標,動態(記住:是動態!)的調用屬於子類的該函數,這樣的函數調用在編譯期間是無法確定的(調用的子類的虛函數的地址無法給出)。因此,這樣的函數地址是在運行期綁定的(晚邦定)。結論就是:重載只是一種語言特性,與多態無關,與物件導向也無關!引用一句Bruce Eckel的話:“不要犯傻,如果它不是晚邦定,它就不是多態。”那麼,多態的作用是什麼呢?我們知道,封裝可以隱藏實現細節,使得代碼模組化;繼承可以擴充已存在的代碼模組(類);它們的目的都是為了——代碼重用。而多態則是為了實現另一個目的——介面重用!多態的作用,就是為了類在繼承和派生的時候,保證使用“家譜”中任一類的執行個體的某一屬性時的正確調用。 概念講解泛化(Generalization)圖表 1 泛化在中,空心的三角表示繼承關係(類繼承),在UML的術語中,這種關係被稱為泛化(Generalization)。Person(人)是基類,Teacher(教師)、Student(學生)、Guest(來賓)是子類。若在邏輯上B是A的“一種”,並且A的所有功能和屬性對B而言都有意義,則允許B繼承A的功能和屬性。例如,教師是人,Teacher 是Person的“一種”(a kind of )。那麼類Teacher可以從類Person派生(繼承)。如果A是基類,B是A的衍生類別,那麼B將繼承A的資料和函數。如果類A和類B毫不相關,不可以為了使B的功能更多些而讓B繼承A的功能和屬性。若在邏輯上B是A的“一種”(a kind of ),則允許B繼承A的功能和屬性。 彙總(組合)圖表 2 組合若在邏輯上A是B的“一部分”(a part of),則不允許B從A派生,而是要用A和其它東西組合出B。例如,眼(Eye)、鼻(Nose)、口(Mouth)、耳(Ear)是頭(Head)的一部分,所以類Head應該由類Eye、Nose、Mouth、Ear組合而成,不是派生(繼承)而成。 彙總的類型分為無、共用(彙總)、複合(組合)三類。 彙總(aggregation) 圖表 3 共用上面圖中,有一個菱形(空心)表示彙總(aggregation)(彙總類型為共用),彙總的意義表示has-a關係。彙總是一種相對鬆散的關係,彙總類B不需要對被彙總的類A負責。 組合(composition)圖表 4 複合這幅圖與上面的唯一區別是菱形為實心的,它代表了一種更為堅固的關係——組合(composition)(彙總類型為複合)。組合表示的關係也是has-a,不過在這裡,A的生命期受B控制。即A會隨著B的建立而建立,隨B的消亡而消亡。 依賴(Dependency)圖表 5 依賴這裡B與A的關係只是一種依賴(Dependency)關係,這種關係表明,如果類A被修改,那麼類B會受到影響。

 

 

UML對很多人來說應該不是一個陌生的概念,這一兩年來,UML被大家越來越多的討論著。本來UML跟我這個主題似乎並不能扯上多大的關係(它是語言無關的,甚至可以說其本身就是一種語言——用於交流的)。我在此談到它有兩個目的:
1. UML是針對物件導向軟體開發的,而C++正是這樣的一種語言
2. UML在設計中被越來越多的使用著,而下一篇雜談準備討論設計模式,如果不瞭解UML,那麼無法進行下去

UML,全稱:Unified Modeling Language,其目的是為了對軟體密集型的製品進行可視化、詳述、構造和文檔化的圖形語言。UML是依據許多前人的思想總結出的成果,1997年被OMG通過並成為標準(所以在《設計模式》書中如果你看到與標準不一樣的地方,不要奇怪,那本書是95年的)。關於UML的曆史和更詳細的描述,可以參考《UML 參考手冊》。UML主要由一系列視圖組成,其中包括靜態視圖(Static view),用例視圖(Use case view)即時檢視(Activity view)等,不同的圖用處自然也不一樣,而對開發人員來講(或者說為我的下一篇來說),更重要的應該是靜態視圖中的類圖(class diagram)和互動視圖(Interaction view)中的順序圖(Sequence diagram),請注意view和diagram的區別。

 類圖
靜態視圖說明了對象的結構,其中最常用的就是類圖,類圖可以協助我們更直觀的瞭解一個系統的體繫結構,有時侯,描述系統快照的對象圖(Object diagram)也是很有用的。在這裡,我們主要介紹類圖,下面的圖就是一個簡單的類圖:

在類圖中,類由矩形框來表示,如中,定義了4個類,分別為Base、A、B、C,類之間的關係通過各種線條和其他符號來表示,在中,空心的三角表示繼承關係,在UML的術語中,這種關係被稱為泛化(Generalization),所以上面的類用等價代碼錶示為:
class Base{…};
class A:public Base{…};
class B:public Base{…};
class C:public Base{…};

我們再看下一幅圖:

這幅圖與上幅幾乎沒有什麼區別,唯一的不同就是Base類中增加了成員,一個私人的integer _x(UML術語為property)和一個公有的fun()的函數(method),是否需要這些類的內部細節UML本身並沒有限制,完全取決於你自己如何使用,UML的用處在於協助你瞭解系統,所以只要你自己覺得足夠清楚,那麼夠了,不要再複雜了。
接著看第三幅圖:
 
上面圖中的箭頭表示一種關係,箭頭另一邊有一個菱形(空心)表示彙總(aggregation),彙總的意義表示has-a關係,其等價代碼如下:
class A{…};
class B{ A* theA;…};
彙總是一種相對鬆散的關係,彙總類B不需要對被彙總的類A負責。
下面的圖:

這幅圖與上面的唯一區別是菱形為實心的,它代表了一種更為堅固的關係——組合(composition)。組合表示的關係也是has-a,不過在這裡,A的生命期受B控制,通常情況,等價代碼如下:
class A{…};
class B{A theA;…};
即A會隨著B的建立而建立,隨B的消亡而消亡。

:

這裡B與A的關係只是一種依賴關係,這種關係表明,如果類A被修改,那麼類B會受到影響,一個簡單的例子就是:
class A{…};
class B{fun(A params);…};

常用的關係就是我們上面用的這些,通過這些關係和類表示的類圖,我們可以用圖形化的方式描述一個系統的設計部分,當你習慣使用UML後,你會發現,這往往比你告訴同伴某某類從某某類派生,衍生類別又和某某類具有什麼關係容易的多。

 順序圖:
UML中另外一個常用的圖形就是互動視圖中的順序圖,在以往的過程化語言中,我們通常使用流程圖來描述一個函數(系統)是如何工作的,而在物件導向的系統中,這顯然是不可行的,而順序圖正是來解決這個問題的。
假設有如下的虛擬碼:

class circle{
public:
void fillcolor()
{
//...
}
void draw()
{
fillcolor();
}
};
class window{
public:
void drawcircle()
{
_circle.draw();
}
private:
circle _circle;
};

對於下面的調用:
window wnd;
wnd.drawcircle();
對應的順序圖如下:
 

 

圖中上方的方塊表示參與的對象,垂直的虛線表示對象的生命線,方框表示啟用,其中箭頭表示了一個調用訊息(也可以有回送return),如果是非同步訊息,則用半箭頭表示,其中draw表示了一個自調用(self call)

至此,UML中最常用的(從開發人員的角度),當然UML的內容遠遠不只這些,這裡的介紹只是一些簡單的概括,並且UML本身也在不斷的發展之中,無論怎樣,我覺得UML會越來越多的深入我們的開發過程中,特別是對下一篇我們要介紹的設計模式而言,類圖是主要的描述工具(到那個時候你會體會到UML描述的優越)。
如果你看過《設計模式》著本書,你會發現與我上面所描述的有一些細微的不同,不要緊張,《設計模式》是GOF95年的作品,那時候UML還沒有形成,而且,其中也明確那是OMT方法(Jim Rumbaugh在通用電氣發表的建模技術——Object Modeling Technique)和Booch方法。如果你覺得UML有些讓你無所適從,也不必緊張,UML本身只是一個協助工具輔助,它的目的是協助你描述系統,不是複雜你的工作,如果你的系統很簡單,一句話可以說的很清楚,那麼不要用UML,如果你只想說明類之間的關係,而不是類的介面描述,那麼像第一副圖那樣簡單的描述就很好,總之不要去追求細節,只要能說明問題,那麼你的目的就達到了(甚至你沒有必要完全遵守規範)。

 參考書目:
《設計模式——可複用物件導向軟體的基礎》 
作者: Erich Gamma 等 譯者:李英軍 馬曉星 蔡敏 劉建中 機械工業出版社2000

《UML參考手冊》作者: James Rumbaugh Ivar Jacobson Grady Booch
譯者: 姚淑珍 唐髮根 機械工業出版社2001

《UML精粹——標準對象建模語言簡明指南(第2版)》
作者: Martin Fowler&Kendall Scott 譯者: 徐家福 清華大學出版社 2002

《Design Patterns Explained》Alan Shalloway, James R. Trott
Addison-Wesley Pub 2001

轉 物件導向的三個基本特徵

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.