《.net編程先鋒C#》第五章 類(轉)

來源:互聯網
上載者:User
編程 第五章 類
前一章討論了資料類型和它們的用法。現在我們轉移到C#中至關重要的結構——類。沒有了
類,就連簡單的C#程式都不能編譯。這一章假定你知道了一個類的基本組成部分:方法、屬性、構

造函數和解構函式。 C#在其中增加了索引和事件。
在這一章中,你學到下列有關類的話題。
。 使用建構函式和解構函式
。給類寫方法
。給一個類增加屬性存取標誌
。實現索引
。建立事件並通過代表元為事件關聯客戶
。應用類、成員和存取修飾符。

5.1 建構函式和解構函式
在你可以訪問一個類的方法、屬性或任何其它東西之前, 第一條執行的語句是包含有相

應類的建構函式。甚至你自己不寫一個建構函式,也會有一個預設的建構函式提供給你。

class TestClass
{
public TestClass(): base() {} // 由編譯器提供
}

一個建構函式總是和它的類名相同,但是,它沒有聲明傳回型別。總之,建構函式總是

public的,你可以用它們來初始設定變數。

public TestClass()
{
// 在這給變數
// 初始化代碼等等。
}

如果類僅包含靜態成員(能以類型調用,而不是以執行個體調用的成員),你可以建立一個

private的建構函式。
private TestClass() {}
儘管存取修飾符在這一章的後面將要大篇幅地討論,但是private意味著從類的外面不可能

訪問該建構函式。所以,它不能被調用,且沒有對象可以自該類定義被執行個體化。
並不僅限於無參數建構函式——你可以傳遞初始參數來初始化成員。
public TestClass(string strName, int nAge) { ... }

作為一個C/C++程式員,你可能習慣於給初始化寫一個附加的方法,因為在建構函式中沒有

傳回值。當然,儘管在C#中也沒有傳回值,但你可以引發一個自製的異常,以從建構函式獲得返回

值。更多有關異常處理的知識在第七章 "異常處理"中有討論。
但是,當你保留引用給寶貴的資源,應該想到寫一個方法來解決:一個可以被顯式地調用來

釋放這些資源。問題是當你可以在解構函式(以類名的前面加"~"的方式命名)中做同樣的事情時,為

何還要寫一個附加的方法.
public ~TestClass()
{
// 清除
}

你應該寫一個附加方法的原因是垃圾收集器,它在變數超出範圍後並不會立即被調用,而僅當

間歇期間或記憶體條件滿足時才被觸發。當你鎖住資源的時間長於你所計劃的時間時,它就會發生。

因此,提供一個顯式的釋放方式是一個好主意,它同樣能從解構函式中調用。

public void Release()
{
// 釋放所有寶貴的資源
}

public ~TestClass()
{
Release();
}

調用解構函式中的釋放方法並不是必要的——總之,垃圾收集會留意釋放對象。但沒有忘記清

除是一種良好的習慣。

5.2 方法
既然對象能正確地初始化和結束,所剩下來的就是往類中增加功能。在大多數情況下,功能的

主要部分在方法中能得到實現。你早已見過靜態方法的使用,但是,這些是類型(類)的部分,不是

執行個體(對象)。
為了讓你迅速入門,我把這些方法的煩瑣問題安排為三節:
。方法參數
。改寫方法
。方法屏蔽
5.2.1 方法參數
因方法要處理更改數值,你多多少少要傳遞值給方法,並從方法獲得傳回值。以下三個部分涉及

到由傳遞值和為調用者擷取返回結果所引起的問題。

。輸入參數
。引用參數
。輸出參數

5.2.1.1 輸入參數
你早已在例子中見過的一個參數就是輸入參數。你用一個輸入參數通過值傳遞一個變數給一個方

法——方法的變數被調用者傳遞進來的值的一個拷貝初始化。清單5.1 示範輸入參數的使用。

清單 5.1 通過值傳遞參數

1: using System;
2:
3: public class SquareSample
4: {
5: public int CalcSquare(int nSideLength)
6: {
7: return nSideLength*nSideLength;
8: }
9: }
10:
11: class SquareApp
12: {
13: public static void Main()
14: {
15: SquareSample sq = new SquareSample();
16: Console.WriteLine(sq.CalcSquare(25).ToString());
17: }
18: }

因為我傳遞值而不是引用給一個變數,所以當調用方法時(見第16行),可以使用一個常量運算式

(25)。整型結果被傳回給調用者作為傳回值,它沒有存到中間變數就被立即顯示到螢幕上 。
輸入參數按C/C++程式員早已習慣的工作方式工作。如果你來自VB,請注意沒有能被編譯器處理

的隱式ByVal或ByRef——如果沒有設定,參數總是用值傳遞。
這點似乎與我前面所陳述的有衝突:對於一些變數類型,用值傳遞實際上意味著用引用傳遞。

迷惑嗎? 一點背景知識也不需要:COM中的東西就是介面,每一個類可以擁有一個或多個介面。一個

介面只不過是一組函數指標,它不包含資料。重複該數組會浪費很多記憶體資源;所以,僅開始地址

被拷貝給方法,它作為調用者,仍然指向介面的相同指標。那就是為什麼對象用值傳遞一個引用。

5.2.1.2 引用參數
儘管可以利用輸入參數和傳回值建立很多方法,但你一想到要傳遞值並原地修改它(也就是在相

同的記憶體位置),就沒有那麼好運了。這裡用引用參數就很方便。
void myMethod(ref int nInOut)
因為你傳遞了一個變數給該方法(不僅僅是它的值),變數必須被初始化。否則,編譯器會警示。

清單 5.2 顯示如何用一個引用參數建立一個方法。

清單 5.2 通過引用傳遞參數

1: // class SquareSample
2: using System;
3:
4: public class SquareSample
5: {
6: public void CalcSquare(ref int nOne4All)
7: {
8: nOne4All *= nOne4All;
9: }
10: }
11:
12: class SquareApp
13: {
14: public static void Main()
15: {
16: SquareSample sq = new SquareSample();
17:
18: int nSquaredRef = 20; // 一定要初始化
19: sq.CalcSquare(ref nSquaredRef);
20: Console.WriteLine(nSquaredRef.ToString());
21: }
22: }

正如所看到的,所有你要做的就是給定義和調用都加上ref限定符。因為變數通過引用傳遞,你

可以用它來計算出結果並傳回該結果。但是,在現實的應用程式中,我強烈建議要用兩個變數,一

個輸入參數和一個引用參數。

5.2.1.3 輸出參數
傳遞參數的第三種選擇就是把它設作一個輸出參數。正如該名字所暗示,一個輸出參數僅用於從

方法傳遞迴一個結果。它和引用參數的另一個區別在於:調用者不必先初始設定變數才調用方法。這

顯示在清單5.3中。

清單 5.3 定義一個輸出參數

1: using System;
2:
3: public class SquareSample
4: {
5: public void CalcSquare(int nSideLength, out int nSquared)
6: {
7: nSquared = nSideLength * nSideLength;
8: }
9: }
10:
11: class SquareApp
12: {
13: public static void Main()
14: {
15: SquareSample sq = new SquareSample();
16:
17: int nSquared; // 不必初始化
18: sq.CalcSquare(15, out nSquared);
19: Console.WriteLine(nSquared.ToString());
20: }
21: }


5.2.2 改寫方法
物件導向設計的重要原則就是多態性。不要理會高深的理論,多態性意味著:當基類程式員已

設計好用於改寫的方法時,在衍生類別中,你就可以重定義(改寫)基類的方法。基類程式員可以用

virtual 關鍵字設計方法:
virtual void CanBOverridden()
當從基類派生時,所有你要做的就是在新方法中加入override關鍵字:
override void CanBOverridden()
當改寫一個基類的方法時,你必須明白,不能改變方法的訪問屬性——在這章的後面,你會學

到更多關於存取修飾詞的知識。
除了改寫基類方法的事實外,還有另一個甚至更重要的改寫特性。當把衍生類別強制轉換成基類

類型並接著調用虛擬方法時,被調用的是衍生類別的方法而不是基類的方法。
((BaseClass)DerivedClassInstance).CanBOverridden();
為了示範虛擬方法的概念,清單 5.4 顯示如何建立一個三角形基類,它擁有一個可以被改

寫的成員方法(ComputeArea)。

清單 5.4 改寫一個基類的方法

1: using System;
2:
3: class Triangle
4: {
5: public virtual double ComputeArea(int a, int b, int c)
6: {
7: // Heronian formula
8: double s = (a + b + c) / 2.0;
9: double dArea = Math.Sqrt(s*(s-a)*(s-b)*(s-c));
10: return dArea;
11: }
12: }
13:
14: class RightAngledTriangle:Triangle
15: {
16: public override double ComputeArea(int a, int b, int c)
17: {
18: double dArea = a*b/2.0;
19: return dArea;
20: }
21: }
22:
23: class TriangleTestApp
24: {
25: public static void Main()
26: {
27: Triangle tri = new Triangle();
28: Console.WriteLine(tri.ComputeArea(2, 5, 6));
29:
30: RightAngledTriangle rat = new RightAngledTriangle();
31: Console.WriteLine(rat.ComputeArea(3, 4, 5));
32: }
33: }

基類Triangle定義了方法ComputeArea。它採用三個參數,返回一個double結果,且具有公用訪

問性。從Triangle類派生出的是RightAngledTriangle,它改寫了ComputeArea 方法,並實現了自己

的面積計算公式。兩個類都被執行個體化,且在命名為TriangleTestApp的應用類的Main() 方法中得到

驗證。
我漏瞭解釋第14行:
class RightAngledTriangle : Triangle
在類語句中冒號(:)表示RightAngledTriangle從類 Triangle派生。那就是你所必須要做的

,以讓C#知道你想把 Triangle當作RightAngledTriangle的基類。
當仔細觀察直角三角形的ComputeArea方法時,你會發現第3個參數並沒有用於計算。但是,利

用該參數就可以驗證是否是“直角”。如清單5.5所示。

清單 5.5 調用基類實現

1: class RightAngledTriangle:Triangle
2: {
3: public override double ComputeArea(int a, int b, int c)
4: {
5: const double dEpsilon = 0.0001;
6: double dArea = 0;
7: if (Math.Abs((a*a + b*b - c*c)) > dEpsilon)
8: {
9: dArea = base.ComputeArea(a,b,c);
10: }
11: else
12: {
13: dArea = a*b/2.0;
14: }
15:
16: return dArea;
17: }
18: }

該檢測簡單地利用了畢達哥拉斯公式,對於直角三角形,檢測結果必須為0。如果結果不為0,類

就調用它基類的 ComputeArea來實現。
dArea = base.ComputeArea(a,b,c);
例子的要點為:通過顯式地利用基類的資格檢查,你就能輕而易舉地調用基類實現改寫方法。
當你需要實現其在基類中的功能,而不願意在改寫方法中重複它時,這就非常有協助。 

相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

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

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