當前位置:編程學習大全網 - 編程語言 - 面向對象程序設計的基本特征?

面向對象程序設計的基本特征?

面向對象三大特性:封裝,繼承,多態

面向對象(Object Oriented,縮寫為OO)是現代軟件技術的精髓。從早期的SmallTalk到如日中天的Java,都滲透著面向對象思想。

OO具有三大特性:封裝性、繼承性和多態性。想掌握面向對象思想,就必須深入理解

其三大特性。這裏我盡量少談概念,只用壹個生活中的例子和壹段代碼來解釋它們。

1、封裝性(Encapsulation)

所謂封裝,就是將某些東西包裝和隱藏起來,讓外界無法直接使用,只能通過某些特定的方式才能訪問。OO將萬物都視為“對象”(Object),任何對象都具有特性和行為。我們將其特性稱為“成員變量” (MemberVarible),將其行為稱之為“成員函數"(Member Function),被封裝的特性只能通過特定的行為去訪問。

大家都見過旅館裏常用的壹種茶葉吧,就是用紙袋把茶葉包裝起來再系是壹根線。用的時候只需要將其放在水杯裏泡就行。這樣的好處是不會將茶葉渣和茶垢弄的滿杯子都是。

好!這就是壹個封裝的例子。

我們喝茶的目的是享受茶葉的香冽;所以茶葉的味道(Flavour)就是茶葉所具有的最

重要特性之壹;可是我們無法直接享受它的清香,因為被外面的紙袋“封裝”起來了。唯壹的辦法就是“泡”(Dilute),將茶袋扔在開水中泡,它的味道就出來了,融入水中。

如果我們把袋裝茶葉看作壹個對象的話,它提供了成員變量Flavour和成員函數Dilute

。並且Flavour是私有(Private)的,我們不能直接把它吞進肚子去,而只能通過成員函

數Dilute才能享受Flavour。

下面用C++代碼來描述這個例子:

Class CTea

{

Private:

Cstring m_Flavour; //味道

Cstring m_Color; //顏色

...... //等等其它屬性

Private:

Void CTea(); //構造函數

Void ~CTea(); //析構函數

Public:

Cstring Dilute();//沏茶

...... //等等其它方法

}

Cstring CTea::Dilute()

{

//怎樣泡出味道來的代碼

}

這就是封裝。通過將對象的某些屬性聲明為Private隱藏起來,只能使用其提供的特定

方法去訪問。

2、繼承(Inheritance)

如果只是封裝,那麽非面向對象語言也能部分的做到。比如在C中,用結構(Struct)、

VB中用自定義類型(Type)也能封裝壹些變量。

OO最有吸引力的特性是繼承。通俗的說後代具有祖先的某些特點就叫繼承,當然後代還可以具有自己獨有的特征。舉個例子吧,菜刀。

菜刀(cutlery)是鋼(Steel)做的,鋼是壹種金屬(Metal),金屬則是大千世界裏的壹種物質(Substance)。所以菜刀的壹些特性可以追溯到物質具有的壹般屬性。正是因為這個道理,MFC中所有類均從CObject繼承而來。

這就是繼承。菜刀直接繼承了鋼的特性,鋼又繼承了金屬的特性,......下面的代碼描

述了這種復雜而有獨特的繼承關系:

Class CSubstance

{

Private:

int m_color;

void CSubstance();

void ~CSubstance();

//......(我是學文科的,具體屬性說不上來)

}

Class CMetal:Public CSubstance

{

void CMetal();

void ~CMetal();

//......

}

Class CSteel:Public CMetal

{

void CSteel();

void ~CSteel();

//......

}

Class CCutlery:Public CSteel

{

private:

Cstring m_Blade;

void CCutlery();

void ~CCutlery();

//......

Public:

void Cut();

}

這裏,CSubstance被稱為基類(Base class),其它被稱為衍生類(Derived class)。衍生類與基類是“Is kind of”的關系。子類與其祖先類之間復雜的函數調用關系不在本文討論之列。

繼承是壹種樹狀的層次關系。子類在繼承祖先類的成員變量和成員函數的同時也可以

定義自己的成員變量和成員函數。比如,Metal 除了繼承了Substance的壹般特性外,還具有自己的屬性諸如可延展性;CCutlery在繼承CSteel的特性後還具有自己的成員諸如“刀刃”(Blade)、“鋒利”(Sharpness)、行為有如“切”(Cut)等。

面向對象技術是對現實生活的抽象,妳可以用生活中的經驗去思考程序設計的邏輯。

3、多態性(Polymorphism)

討論多態之前先要明白什麽是“虛擬”(Virtual)。C++/MFC就是用虛擬這種方式實現多態的。為什麽“虛擬”這個概念?看下邊的例子:

Class Cincect //昆蟲類

{

private:

int m_foot; //腳的數量

...... //其它成員變量

private:

void Cincect();

void ~Cincect();

public:

void Bite()//咬人

{

...... //怎樣咬人的代碼,比如張開嘴啃

}

}

我把Bite(咬)這個動作在基類中定義為壹般化動作。可是,不是所有昆蟲咬

人的方法都壹樣(況且還有的根本就不咬人呢,比如蜻蜓),比如蚊子是用嘴那個

吸管叮人而螞蟻是用嘴去夾。

從昆蟲這個類別衍生出以下兩個類別:Cant(螞蟻)、Cmosquito(蚊子)。

class Cant :public Cincect //螞蟻類

{

......

}

class Cmosquito :public Cincect //蚊子類

{

......

}

它們都繼承了Cincect的所有成員,當然也繼承了Bite()這個動作。現在就有問題了:

同樣繼承自昆蟲,當我們使用Bite()這個動作時怎麽才能區分螞蟻和蚊子各自的獨有的咬人方式呢?

方法之壹是用“::”符號指明具體引用的是那壹個,但這樣明顯失去了靈活性;

另壹種方法就是“虛擬”。使用關鍵字virtual將Bite()聲明為虛擬函數,然後在每個

衍生類中重新定義,描述它們各自的咬人方法,調用的時候也不會都壹種結果啦。於是上邊的例子可以改寫為:

Class Cincect //昆蟲類

{

private:

int m_foot; //腳的數量

...... //其它成員變量

private:

void Cincect();

void ~Cincect();

public:

virtual Bite(){}//咬人,但我們只聲明這個成員函數,

//卻讓它什麽動作都不做,讓衍生類自己去定

//義各自的咬人方法

}

class Cant :public Cincect //螞蟻類

{

......

virtual Bite();

}

Cant::Bite()

{

...... //螞蟻具體的咬人方式

}

class Cmosquito :public Cincect //蚊子類

{

......

virtual Bite();

}

Cmosquito::Bite()

{

...... //蚊子具體的咬人方式

}

所以,虛擬的目的是只在基類中將壹般化動作聲明壹個成員函數的原型而不做

具體定義,讓衍生類自己去定義。

這就是面向對象的特征之三:多態性。基類的同壹個成員在不同的衍生類中可以具

有不同的形態,更好地抽象和描述大千世界中的諸多“對象”。

1.了解什麽是多態性

2.如何定義壹個虛方法

3.如何重載壹個虛方法

4.如何在程序中運用多態性

面向對象程序設計中的另外壹個重要概念是多態性。在運行時,可以通過指向基類的指針,來調用實現派生類中的方法。 可以把壹組對象放到壹個數組中,然後調用它們的方法,在這種場合下,多態性作用就體現出來了,這些對象不必是相同類型的對象。當然,如果它們都繼承自某個類,妳可以把這些派生類,都放到壹個數組中。 如果這些對象都有同名方法,就可以調用每個對象的同名方法。本節課將向妳介紹如何完成這些事情。

1.清單9-1. 帶有虛方法的基類:DrawingObject.cs

using System;

public class DrawingObject

{

public virtual void Draw()

{

Console.WriteLine("I'm just a generic drawing object.");

}

}

說明

清單9-1 定義了DrawingObject類。這是個可以讓其他對象繼承的基類。該類有壹個名為Draw()的方法。Draw()方法帶有壹個virtual修飾符,該修飾符表明:該基類的派生類可以重載該方法。DrawingObject類的 Draw()方法完成如下事情:輸出語句"I'm just a generic drawing object."到控制臺。

2.清單9-2. 帶有重載方法的派生類:Line.cs, Circle.cs, and Square.cs

using System;

public class Line : DrawingObject

{

public override void Draw()

{

Console.WriteLine("I'm a Line.");

}

}

public class Circle : DrawingObject

{

public override void Draw()

{

Console.WriteLine("I'm a Circle.");

}

}

public class Square : DrawingObject

{

public override void Draw()

{

Console.WriteLine("I'm a Square.");

}

}

說明

清單9-2定義了三個類。這三個類都派生自DrawingObject類。每個類都有壹個同名Draw()方法,這些Draw()方法中的每壹個都有壹個重載修飾符。重載修飾符可讓該方法在運行時重載其基類的虛方法,實現這個功能的條件是:通過基類類型的指針變量來引用該類。

3.清單9-3. 實現多態性的程序:DrawDemo.cs

using System;

public class DrawDemo

{

public static int Main(string[] args)

{

DrawingObject[] dObj = new DrawingObject[4];

dObj[0] = new Line();

dObj[1] = new Circle();

dObj[2] = new Square();

dObj[3] = new DrawingObject();

foreach (DrawingObject drawObj in dObj)

{

drawObj.Draw();

}

return 0;

}

}

說明

清單9-3演示了多態性的實現,該程序使用了在清單 9-1 和清單9-2中定義的類。在DrawDemo類中的Main()方法中,創建了壹個數組, 數組元素是DrawingObject 類的對象。該數組名為dObj,是由四個DrawingObject類型的對象組成。

接下來, 初始化dObj數組, 由於Line, Circle和Square類都是DrawingObject類的派生類,所以這些類可以作為dObj數組元素的類型。 如果C#沒有這種功能,妳得為每個類創建壹個數組。繼承的性質可以讓派生對象當作基類成員壹樣用,這樣就節省了編程工作量。

壹旦數組初始化之後,接著是執行foreach循環,尋找數組中的每個元素。在每次循環中, dObj 數組的每個元素(對象)調用其Draw()方法。多態性體現在:在運行時,各自調用每個對象的Draw()方法。盡管dObj 數組中的引用對象類型是DrawingObject,這並不影響派生類重載DrawingObject 類的虛方法Draw()。 在dObj 數組中,通過指向DrawingObject 基類的指針來調用派生類中的重載的Draw()方法。

輸出結果是:

I'm a Line.

I'm a Circle.

I'm a Square.

I'm just a generic drawing object.

在DrawDemo 程序中,調用了每個派生類的重載的Draw()方法。 最後壹行中,執行的是DrawingObject類的虛方法Draw()。這是因為運行到最後,數組的第四個元素是DrawingObject類的對象。

小結

現在對多態性有所了解之後,妳可以在派生類中,實現壹個重載基類虛方法的方法。虛方法和重載的派生類方法之間的關系就體現出C#的多態性。

  • 上一篇:大家用漢語編程都用什麽軟件(壹般軟件用什麽編程語言)
  • 下一篇:方案編制中的平等
  • copyright 2024編程學習大全網