- Visual C# 2008開發(fā)技術(shù)詳解
- 李容等編著
- 2288字
- 2018-12-27 11:19:37
第3章 C#面向?qū)ο蠡A(chǔ)
面向?qū)ο缶幊痰挠⑽暮?jiǎn)稱是OOP(Object Oriented Programming),該項(xiàng)技術(shù)是目前運(yùn)用最廣泛的程序化設(shè)計(jì)方法,幾乎已經(jīng)完全取代了過(guò)去的面向過(guò)程編程。C#從一誕生開始,就是為面向?qū)ο缶幊趟鶞?zhǔn)備的。類是面向?qū)ο缶幊痰暮诵牟考枋隽艘唤M具有相同特性和行為的對(duì)象。基于面向?qū)ο蟮膽?yīng)用程序,就是由幾個(gè)或幾十個(gè)甚至更多的類組成,且類之間總是保持著或多或少的關(guān)系。類其實(shí)也是數(shù)據(jù)類型,所以在面向?qū)ο缶幊讨谐绦騿T可以自定義數(shù)據(jù)類型,這和面向過(guò)程編程是有本質(zhì)區(qū)別的。
本章主要內(nèi)容:
● 類的定義
● 類的數(shù)據(jù)成員和函數(shù)成員
● 事件和委托
● 接口的使用
● 面向?qū)ο蟮娜筇卣?/p>
● 其他面向?qū)ο蟮闹黝}
3.1 類的基本概念
在C#中,類可以看成是一種數(shù)據(jù)結(jié)構(gòu),它自身封裝了數(shù)據(jù)成員和函數(shù)成員等。其中數(shù)據(jù)成員包括字段、常量和域等,而函數(shù)成員主要包括方法、屬性、事件、索引器和操作符等。本節(jié)將對(duì)類的結(jié)構(gòu)和用法進(jìn)行詳細(xì)說(shuō)明。
3.1.1 C#中的類定義
在C#中,用class關(guān)鍵字來(lái)定義類,基本結(jié)構(gòu)如下所示。
[attributes] [modifiers] class identifier [:base-list] { class-body }
其中attributes表示附加的聲明信息,modifiers表示類的訪問(wèn)修飾符,identifier表示類的名稱,base-list表示繼承的基類和實(shí)現(xiàn)的接口的列表,基類在前,接口在后,且用逗號(hào)隔開。
在C#中,類的訪問(wèn)修飾符主要分為public、private、protected和internal。它們的具體用法如下所示。
public:它具有最高的訪問(wèn)級(jí)別,對(duì)訪問(wèn)公共成員沒(méi)有限制; private:它的訪問(wèn)級(jí)別最低,僅限于它的包含類; protected:能在它的包含類或包含類的派生類中訪問(wèn); internal:只能在同一程序集的文件中。
原則上,一個(gè)類只能使用一種訪問(wèn)修飾符,但有一個(gè)特例需要注意,具體如下所示。
protected internal:僅限于從包含類派生的當(dāng)前程序集或類型。
還有一些修飾符能與以上修飾符相結(jié)合,得到一些特殊的限制,比如abstract和sealed等,如下所示。
public abstract:可以在任何地方訪問(wèn),但不能實(shí)例化,只能繼承; public sealed:可以在任何地方訪問(wèn),只能實(shí)例化,不能派生。
3.1.2 字段
字段實(shí)際上相當(dāng)于類的變量,它在類中的應(yīng)用十分廣泛,看一個(gè)簡(jiǎn)單的例子,如下面代碼所示。
public class Car { public string Name; public string Color; public double Price; } Car car = new Car(); car.Name="BMW"; car.Color="White"; car.Price=80000.00;
在上例中,定義了一個(gè)Car類,它包含了三個(gè)字段,分別為Name、Color和Price。通過(guò)在類的外部對(duì)該類進(jìn)行實(shí)例化,對(duì)類的字段進(jìn)行賦值。這里需要注意的是,類中的字段也必須要定義成public類型才能在類的外部被訪問(wèn)。
3.1.3 常量
常量在類中所處的地位和字段差不多,只是它不可變而已。通常,定義常量用關(guān)鍵字const,如下面代碼所示。
public const int age = 25;
3.1.4 域
域的聲明過(guò)程和字段比較相似,但它們之間有一個(gè)很重要的區(qū)別,即域只能聲明在類的內(nèi)部,而不能聲明在類的方法的內(nèi)部。域分為實(shí)例域和靜態(tài)域,實(shí)例域只能通過(guò)類的實(shí)例進(jìn)行調(diào)用,而靜態(tài)域可以直接通過(guò)類名進(jìn)行調(diào)用。下面看一個(gè)例子,代碼如下。
class Student { public static int count = 37; //聲明域 static void Main(string[] args) { Console.WriteLine("學(xué)生人數(shù)為:"+Student.count.ToString()); Console.ReadKey(); } }
運(yùn)行結(jié)果如圖3-1所示。

圖3-1 運(yùn)行結(jié)果圖
以上代碼聲明了一個(gè)靜態(tài)域count,因?yàn)槭庆o態(tài)的,所以它能直接用類名進(jìn)行調(diào)用。此外,域也可以分為公有域和私有域。公有域可以在類的外部被修改,而私有域(也稱為只讀域)不能在類的外部被修改,聲明私有域的關(guān)鍵字是readonly,如下面的例子所示。
class Student { public readonly int count = 37; //聲明私有域 static void Main(string[] args) { Student sd = new Student(); Console.WriteLine("學(xué)生人數(shù)為:"+sd.count++); Console.ReadKey(); } }
如果試圖運(yùn)行該程序,會(huì)出現(xiàn)如圖3-2所示的錯(cuò)誤信息。

圖3-2 錯(cuò)誤列表
這是因?yàn)橛騝ount是私有域,用readonly關(guān)鍵字標(biāo)識(shí)的私有域不能在外部被修改。如果去掉readonly關(guān)鍵字,則count變?yōu)楣杏颍藭r(shí)運(yùn)行后輸出結(jié)果如圖3-3所示。

圖3-3 運(yùn)行結(jié)果
3.1.5 類的方法
在C#中,方法的定義與其他語(yǔ)言一樣,包括三個(gè)部分,分別為訪問(wèn)修飾符、輸入?yún)?shù)和返回類型。方法的訪問(wèn)修飾符的類型和類的差不多,如表3-1所示。
表3-1 方法修飾符

類的方法被創(chuàng)建以后,必須要被調(diào)用才有意義。下面的代碼是調(diào)用類的方法的例子。
public abstract class Compute { public virtual int Method(int x, int y) { return x + y; } } public class Use:Compute { public override int Method(int x, int y) { return base.Method(x, y); } static void Main(string[] args) { Use use = new Use(); Console.WriteLine(use.Method(2,3)); Console.ReadKey(); } }
上面的代碼中首先定義一個(gè)抽象類Compute,它只能被繼承,此外它包含了一個(gè)虛擬方法Method(),該方法只能在它的包含類的派生類中被重寫后才能使用。然后定義Compute類的派生類Use,并且在Use類中重寫Method()方法。最后通過(guò)實(shí)例化Use類,輸出結(jié)果,如圖3-4所示。

圖3-4 運(yùn)行結(jié)果
方法被調(diào)用時(shí),參數(shù)傳遞十分重要。同其他編程語(yǔ)言一樣,C#中方法的參數(shù)傳遞也分為值傳遞和引用傳遞。它們之間的區(qū)別比較難以理解,下面通過(guò)例子來(lái)說(shuō)明。
public class Use { public int Method1(int x) { x=3*x; return x; } public int Method2(ref int x) { x=3*x; return x; } static void Main(string[] args) { Use use = new Use(); int x = 2; Console.WriteLine("輸出結(jié)果是:" + use.Method2(ref x)); //輸出引用傳遞 //的結(jié)果 Console.WriteLine("輸出結(jié)果是:"+use.Method1(x)); //輸出值傳遞的結(jié)果 Console.ReadKey(); }
以上代碼主要定義了兩個(gè)方法,Method1()是值參數(shù)類型,而Method2()引用參數(shù)類型,最后輸出它們的結(jié)果,如圖3-5所示。

圖3-5 運(yùn)行結(jié)果
此時(shí),將兩個(gè)輸出語(yǔ)句的順序顛倒,具體如下所示。
Console.WriteLine("輸出結(jié)果是:"+use.Method1(x)); //輸出值傳遞的結(jié)果 Console.WriteLine("輸出結(jié)果是:" + use.Method2(ref x)); //輸出引用傳遞的結(jié)果
此時(shí)再看輸出結(jié)果,如圖3-6所示。

圖3-6 運(yùn)行結(jié)果
比較以上兩個(gè)輸出結(jié)果,發(fā)現(xiàn)并不相同。原因是引用參數(shù)使方法引用的是原來(lái)的變量,而值參數(shù)引用的僅是原來(lái)變量的副本。交換輸出語(yǔ)句前的程序中,因?yàn)橄日{(diào)用了引用參數(shù)傳遞,所以更改了原來(lái)的變量,使x從2變成了6,所以值傳遞的結(jié)果為18。相反,當(dāng)值傳遞先被調(diào)用時(shí),它并沒(méi)有改變?cè)瓉?lái)的變量,所以兩個(gè)輸出結(jié)果均為6。
3.1.6 類的屬性
類的屬性提供比較靈活的機(jī)制來(lái)讀取、編寫或計(jì)算私有字段的值,可以像使用公有數(shù)據(jù)成員一樣使用屬性。屬性必須要由訪問(wèn)器進(jìn)行讀寫,它的一般聲明格式如下所示。
[attributes] [modifiers] type identifier { declaration }
其中attributes表示附加的聲明信息,modifiers表示修飾符,和類的方法的修飾符差不多,type表示屬性類型,declaration表示對(duì)屬性的讀寫操作。如下面的例子所示。
class Fruit { private string name; public string Name { get { return name; } set { name = value; } } static void Main(string[] args) { Fruit fr = new Fruit(); fr.Name = "Apple"; Console.WriteLine("這種水果為:"+fr.Name); Console.ReadKey(); } }
運(yùn)行結(jié)果如圖3-7所示。

圖3-7 運(yùn)行結(jié)果
屬性的一個(gè)重要特點(diǎn)是含有g(shù)et和set訪問(wèn)器,set用于寫,get用于讀。它們也可以缺省,只含有g(shù)et訪問(wèn)器的屬性為只讀屬性,只含有set訪問(wèn)器的屬性為只寫屬性。將上面的代碼替換為如下所示代碼。
class Fruit { private string name; public string Name { get { return name; } } static void Main(string[] args) { Fruit fr = new Fruit(); fr.name = "Apple"; Console.WriteLine("這種水果為:"+fr.Name); Console.ReadKey(); } }
此時(shí)的Name為只讀屬性,所以必須要對(duì)name進(jìn)行賦值才能正確輸出結(jié)果,輸出結(jié)果與圖3-7一致。
3.1.7 類的索引器
索引器是C#所特有的類成員,它的主要作用是對(duì)象能向數(shù)組一樣被方便地引用。索引器的聲明與屬性的聲明比較類似,如下所示。
Public type this[index] { get { //代碼 } set { //代碼 } }
索引器具有以下特點(diǎn)。
(1)索引器沒(méi)有具體的名字,需要用this關(guān)鍵字對(duì)對(duì)象進(jìn)行索引。this關(guān)鍵字指向被訪問(wèn)成員所在的當(dāng)前實(shí)例,可以在構(gòu)造函數(shù)和實(shí)例方法中實(shí)現(xiàn)對(duì)成員的訪問(wèn),但不能訪問(wèn)靜態(tài)成員。
(2)索引器不能定義為靜態(tài)的。
(3)索引器的參數(shù)index只能是傳值類型,不能出現(xiàn)ref和out關(guān)鍵字。
下面是一個(gè)關(guān)于索引器的例子。
class Student { public string[] Name = new string[10]; public Student() { for (int i = 0; i < 10; i++) { Name[i] = i.ToString(); } } public string this[int index] //創(chuàng)建索引器 { get { string str; if (index >= 0 && index < 10) { str = Name[index]; } else { str = "null"; } return str; } set { if (index >= 0 && index < 10) { Name[index] = value; } } } static void Main(string[] args) { Student sd = new Student(); sd[3] = "zhangwei"; sd[4] = "weiyi"; sd[5] = "lirong"; for (int i = 0; i < 12; i++) { Console.WriteLine(sd[i]); } Console.ReadKey(); } }
上面的代碼通過(guò)索引器實(shí)現(xiàn)了對(duì)Name數(shù)組的訪問(wèn),運(yùn)行結(jié)果如圖3-8所示。

圖3-8 運(yùn)行結(jié)果
3.1.8 類的構(gòu)造函數(shù)和析構(gòu)函數(shù)
類的構(gòu)造函數(shù)能被編譯器自動(dòng)執(zhí)行,它具有以下特點(diǎn)。
(1)構(gòu)造函數(shù)必須與類同名。
(2)構(gòu)造函數(shù)不能有返回類型。
(3)當(dāng)訪問(wèn)一個(gè)類時(shí),它的構(gòu)造函數(shù)最先被執(zhí)行。
(4)一個(gè)類可以有多個(gè)構(gòu)造函數(shù),如果沒(méi)有定義構(gòu)造函數(shù),系統(tǒng)會(huì)自動(dòng)生成一個(gè)默認(rèn)的構(gòu)造函數(shù)。
構(gòu)造函數(shù)又分為實(shí)例構(gòu)造函數(shù)和靜態(tài)構(gòu)造函數(shù),其區(qū)別如表3-2所示。
表3-2 實(shí)例構(gòu)造函數(shù)與靜態(tài)構(gòu)造函數(shù)

下面通過(guò)例子進(jìn)行說(shuō)明,示例代碼如下。
class Student { public static int x; public int y; public int z; public int m; public int n; //構(gòu)造函數(shù)一 public Student() { y = 2; z = 2; } //構(gòu)造函數(shù)二 public Student(int m, int n) { this.m = m; this.n = n; } //構(gòu)造函數(shù)三 static Student() { x = 5; } static void Main(string[] args) { Console.WriteLine("x="+Student.x); Student sd1 = new Student(); Console.WriteLine("y={0}, z={1}", sd1.y, sd1.z); Student sd2 = new Student(3,3); Console.WriteLine("m={0}, n={1}", sd2.m, sd2.n); Console.ReadKey(); } }
本例共為Student類創(chuàng)建了三個(gè)構(gòu)造函數(shù),其中構(gòu)造函數(shù)三是靜態(tài)構(gòu)造函數(shù)。例子運(yùn)行結(jié)果如圖3-9所示。

圖3-9 運(yùn)行結(jié)果
類的析構(gòu)函數(shù)與構(gòu)造函數(shù)的過(guò)程剛剛相反,它主要用于銷毀類的實(shí)例。它不能帶有參數(shù),不能含有修飾符,不能被調(diào)用,且它也必須與類同名。為了區(qū)別于構(gòu)造函數(shù),通常在前面加符號(hào)“~”。其語(yǔ)法如下所示。
class Student { …… ~Student() { …… } }
析構(gòu)函數(shù)通常會(huì)被自動(dòng)執(zhí)行,只有一些非常特殊的情況下才需要被用到,比如非托管資源的清理。
3.1.9 事件
事件相關(guān)知識(shí)的內(nèi)容太多,在本章的后面部分將用單獨(dú)一節(jié)進(jìn)行講解。
3.2 Visual Studio中的類向?qū)?/h3>
在Visual Studio 2008(以下簡(jiǎn)稱VS2008)中,提供了創(chuàng)建類和類的成員的快捷方式,在本節(jié)中將通過(guò)例子進(jìn)行詳細(xì)說(shuō)明。其創(chuàng)建步驟如下。
(1)打開VS2008,在D:\C#\ch3目錄下建立名為“ClassWizard”的控制臺(tái)應(yīng)用程序。打開“解決方案資源管理器”界面,右鍵單擊當(dāng)前工程“ClassWizard”,選擇“添加”—“新建項(xiàng)”命令,添加新類Book.cs,如圖3-10所示。

圖3-10 添加類
(2)選擇“視圖”—“類視圖”菜單,如圖3-11所示。

圖3-11 類視圖
此時(shí)可以看出當(dāng)前工程的類的結(jié)構(gòu)圖,包含兩個(gè)類,Book類和Program類,其中Book類是剛被創(chuàng)建的,而Program類是隨工程一起被創(chuàng)建的。在圖3-11中,下半部分窗格主要是顯示被選中類的具體成員。因?yàn)锽ook類是剛被創(chuàng)建的,所以它不含有任何成員。
(3)現(xiàn)在開始為Book類添加成員,在圖3-11中,右鍵單擊“Book”,選擇“查看類關(guān)系圖”命令,彈出如圖3-12所示的對(duì)話框。右鍵單擊空白處,選擇“添加”命令,其菜單如圖3-13所示。

圖3-12 類的關(guān)系圖

圖3-13 添加類的成員
(4)為Book類添加一個(gè)bookname字段,其屬性設(shè)置如圖3-14所示;然后添加一個(gè)Price屬性,如圖3-15所示。

圖3-14 添加字段

圖3-15 添加屬性
(5)接著再添加方法Count,如圖3-16所示。

圖3-16 添加方法
(6)添加完以上成員后,在“解決方案資源管理器”下打開Book.cs,代碼如下所示。
class Book { private string[] bookname; public double Price { get { throw new System.NotImplementedException(); } set { } } public double Count() { throw new System.NotImplementedException(); } }
從以上代碼可以看出,bookname字段、Price屬性和Count方法已經(jīng)添加到Book類中。其中.NotImplementedException()表示無(wú)法實(shí)現(xiàn)請(qǐng)求的方法或操作時(shí)引發(fā)的異常。將上面的代碼替換為如下所示代碼。
class Book { //字段 public string[] bookname = new string[4]; public double price; //屬性 public double Price { get { return price; } set { price = value; } } //方法 public double Count(double Price) { Price = Price * 0.8; return Price; } }
在Main()函數(shù)中添加如下代碼。
Book book = new Book(); book.bookname[0] = "C# Programming"; book.bookname[1] = "C++ Programming"; book.bookname[2] = "C Programming"; book.bookname[3] = "Java Programming"; for (int i = 0; i < 4; i++) { Console.WriteLine("書名:" + book.bookname[i]); Console.WriteLine("原價(jià):"); string s = Console.ReadLine(); Console.WriteLine("打折后的價(jià)格:"); Console.WriteLine(book.Count(Convert.ToDouble(s))); } Console.ReadKey();
程序運(yùn)行結(jié)果如圖3-17所示。

圖3-17 程序運(yùn)行結(jié)果
本例主要是通過(guò)VS2008中的類向?qū)?shí)現(xiàn)了類成員的添加,完成的功能是將Book類中的書名,書的原價(jià)和書打折后的價(jià)格輸出。
3.3 事件和委托
事件是C#中的又一個(gè)重要概念,在發(fā)生其他類或?qū)ο笮枰P(guān)注的事情時(shí),本類或?qū)ο罂梢酝ㄟ^(guò)事件來(lái)通知它們。發(fā)送事件的類稱為事件的發(fā)送者,而接收事件的類稱為事件的訂閱戶。
3.3.1 委托
委托是事件應(yīng)用過(guò)程中必不可少的一個(gè)環(huán)節(jié),委托首先是在Visual J++中提出的,后來(lái)被C#引用。如果一個(gè)類需要調(diào)用另一個(gè)類的方法,可以有三種方式,即實(shí)例方式、靜態(tài)方式和委托方式。應(yīng)用委托調(diào)用方法的流程如圖3-18所示。

圖3-18 委托使用流程圖
下面通過(guò)一個(gè)例子來(lái)說(shuō)明委托的具體用法。打開VS2008,在D:\C#\ch3目錄下建立名為DelegateTest的控制臺(tái)應(yīng)用程序。打開工程,添加如下代碼。
class Test { public delegate void Mydelegate(string str); //聲明委托 public int s = 3; public void Method1(string str) //方法一 { s = 5; } public void Method2(string str) //方法二 { s = 7; } public void Call(Mydelegate d, string str) //調(diào)用委托中的方法 { d(str); Console.WriteLine(str); } static void Main(string[] args) { Test test = new Test(); Mydelegate d1 = new Mydelegate(test.Method1); //在委托中包含方法一 Mydelegate d2 = new Mydelegate(test.Method2); //在委托中包含方法二 test.Call(d2, "成功調(diào)用了委托"); Console.WriteLine("輸出結(jié)果:"+test.s.ToString()); Console.ReadKey(); } }
代碼說(shuō)明如下。
(1)首先需要定義委托,使用的關(guān)鍵字是delegate,代碼如下所示。
public delegate void Mydelegate(string str); //聲明委托
它的返回類型和參數(shù)必須要和它調(diào)用的方法的返回類型和參數(shù)相匹配。
(2)接下來(lái)是定義該委托需要調(diào)用的方法,本例定義了兩個(gè)方法,用于對(duì)字段s進(jìn)行不同的修改,如下所示。
public void Method1(string str) //方法一 { s = 5; } public void Method2(string str) //方法二 { s = 7; }
(3)創(chuàng)建委托對(duì)象,對(duì)聲明的方法進(jìn)行包含,如下所示。
Test test = new Test(); Mydelegate d1 = new Mydelegate(test.Method1); //在委托中包含方法一 Mydelegate d2 = new Mydelegate(test.Method2); //在委托中包含方法二
(4)最后即是完成方法的調(diào)用,如下所示。
public void Call(Mydelegate d, string str) //調(diào)用委托中的方法 { d(str); Console.WriteLine(str); }
這里使用了兩個(gè)參數(shù),第一個(gè)是創(chuàng)建的委托對(duì)象,它能直接通過(guò)要調(diào)用方法的參數(shù)完成對(duì)方法的調(diào)用,第二個(gè)參數(shù)是調(diào)用的方法的參數(shù)。程序的運(yùn)行結(jié)果如圖3-19所示。

圖3-19 運(yùn)行結(jié)果
3.3.2 委托的事件處理程序
前面提到,事件需要訂閱者,當(dāng)事件發(fā)生時(shí),訂閱者會(huì)給出相應(yīng)的事件處理程序。事件處理程序本身是簡(jiǎn)單的函數(shù)形式,它的參數(shù)和返回類型必須和調(diào)用它的委托相匹配。委托在這里的作用是包含事件處理程序,當(dāng)事件被觸發(fā)時(shí),通過(guò)委托來(lái)執(zhí)行事件處理程序。下面通過(guò)例子進(jìn)行說(shuō)明,主要功能是通過(guò)在Class2中定義并觸發(fā)事件,在Class1中調(diào)用事件處理程序。
打開VS2008,在D:\C#\ch3目錄下建立名為EventTest的控制臺(tái)應(yīng)用程序,打開工程,添加如下所示代碼。
namespace EventTest { //繼承 public class MyEventArgs : EventArgs { public string str; } //聲明委托對(duì)象 public delegate void MyEventHandler1(object sender, MyEventArgs e); class Class1 { //創(chuàng)建委托對(duì)象并包含事件處理函數(shù) public Class1(Class2 class2) { MyEventHandler1 mh1 = new MyEventHandler1(Method1); //訂閱事件 class2.Event1 += mh1; } //事件處理函數(shù) public void Method1(object sender, MyEventArgs e) { Console.WriteLine("事件處理結(jié)果:"+e.str); } } //通過(guò)委托來(lái)調(diào)用被包含的方法 class Class2 { //定義事件 public event MyEventHandler1 Event1; //觸發(fā)事件 public void mEvent1(MyEventArgs e) { if (Event1 ! = null) { Event1(this, e); } } } class Class3 { static void Main(string[] args) { Class2 class2 = new Class2(); Class1 class1 = new Class1(class2); MyEventArgs e1 = new MyEventArgs(); e1.str = "aaa"; class2.mEvent1(e1); Console.ReadKey(); } } }
代碼說(shuō)明如下。
(1)首先還是需要定義委托,事件中的委托和普通委托有一定的區(qū)別,它的參數(shù)形式比較固定,如下所示。
public delegate void MyEventHandler1(object sender, MyEventArgs e);
事件中的委托具有兩個(gè)參數(shù),第一個(gè)參數(shù)表示事件的觸發(fā)對(duì)象,第二個(gè)參數(shù)表示處理事件的對(duì)象,它是從EventArgs類繼承而來(lái),EventArgs類包含很多事件處理對(duì)象類,在GUI中比較常見,如鼠標(biāo)事件處理類MouseEventArgs。本例的MyEventArgs是從EventArgs中繼承而來(lái)(有關(guān)繼承的知識(shí)將會(huì)在本章后面部分講解),如下所示。
public class MyEventArgs : EventArgs { public string str; }
(2)接下來(lái)需要在Class2中完成事件的聲明和觸發(fā),如下所示。
class Class2 { //定義事件 public event MyEventHandler1 Event1; public void mEvent1(MyEventArgs e) { if (Event1 ! = null) { //觸發(fā)事件 Event1(this, e); } } }
(3)在Class1類中定閱事件并編寫事件處理程序,如下所示。
class Class1 { //創(chuàng)建委托對(duì)象并包含事件處理函數(shù) public Class1(Class2 class2) { MyEventHandler1 mh1 = new MyEventHandler1(Method1); //訂閱事件 class2.Event1 += mh1; } //事件處理函數(shù) public void Method1(object sender, MyEventArgs e) { Console.WriteLine("事件處理結(jié)果:"+e.str); } }
在Class1中完成了Class2的Event1事件的訂閱,以上工作由委托mh1完成。相應(yīng)的事件處理代碼包含在Method1()中。
(4)最后,輸出事件處理結(jié)果,如下所示。
Class2 class2 = new Class2(); Class1 class1 = new Class1(class2); MyEventArgs e1 = new MyEventArgs(); e1.str = "aaa"; class2.mEvent1(e1); Console.ReadKey();
程序的運(yùn)行結(jié)果如圖3-20所示。

圖3-20 運(yùn)行結(jié)果
3.3.3 委托中的GUI事件
從上一節(jié)的例子可以看出,事件的應(yīng)用步驟是比較復(fù)雜的。在.NET Framework中,運(yùn)用事件最多的部分是GUI控件,比如Button的Click(單擊)事件。是不是每應(yīng)用一次事件就必須做出與上例相似的操作?答案是否定的。在GUI事件的應(yīng)用中,.NET Framework已經(jīng)完成了大量的工作,下面通過(guò)例子進(jìn)行說(shuō)明。
注意:以下例子會(huì)用到控件知識(shí),不懂控件的讀者可先跳過(guò)這部分。
打開VS2008,在D:\C#\ch3目錄下建立名為GUIEventTest的Windows應(yīng)用程序,打開工程,為當(dāng)前窗體添加一個(gè)Button控件。右鍵單擊該Button控件對(duì)象,選擇“屬性”,轉(zhuǎn)到“屬性”的“事件”窗口,如圖3-21所示。

圖3-21 事件窗口
從圖3-21可以看出,Button包含了很多事件,雙擊Click事件,窗口中顯示的代碼如下所示。
private void button1_Click(object sender, EventArgs e) { }
button1_Click()為事件處理函數(shù),它具有兩個(gè)參數(shù),這在前面已經(jīng)講過(guò)。需要注意的是它使用的事件處理對(duì)象EventArgs類。此時(shí),打開Form1.Designer.cs,在有關(guān)Button的設(shè)計(jì)器代碼中有如下語(yǔ)句。
this.button1.Click += new System.EventHandler(this.button1_Click);
可見,編譯器已經(jīng)訂閱好了該事件,讀者需要做的工作僅是向button1_Click()中添加程序執(zhí)行代碼。比如添加如下所示代碼。
this.Text = "GUI事件";
完成對(duì)當(dāng)前窗體標(biāo)題的修改,運(yùn)行程序,結(jié)果如圖3-22所示。

圖3-22 運(yùn)行結(jié)果
本節(jié)主要介紹了C#中的事件處理機(jī)制及委托的用法。C#中的事件主要分為兩類,一類是GUI事件,.NET Framework為這類事件的應(yīng)用做了大量工作,它的使用較簡(jiǎn)單;另一類是非GUI事件,它的事件聲明、訂閱和處理都需要讀者自己編寫,使用比較復(fù)雜,但在一些場(chǎng)合它是很必要的。總的來(lái)說(shuō),事件具有以下特點(diǎn)。
(1)事件的發(fā)送者決定何時(shí)發(fā)送事件,事件的訂閱者決定執(zhí)行何種操作來(lái)響應(yīng)事件。
(2)一個(gè)事件可以同時(shí)有多個(gè)訂閱者,一個(gè)訂閱者可以響應(yīng)多個(gè)事件。
(3)沒(méi)有訂閱者的事件不會(huì)被調(diào)用。
(4)具有多個(gè)訂閱者的事件被觸發(fā)時(shí),會(huì)同步調(diào)用多個(gè)事件處理程序。
(5)在.NET Framework中,事件是基于EventHandler委托和EventArgs基類的。
通過(guò)本節(jié)的學(xué)習(xí),讀者應(yīng)該對(duì)事件有了一個(gè)比較初步的認(rèn)識(shí),在以后的章節(jié)中具體的應(yīng)用場(chǎng)合還會(huì)繼續(xù)講解事件。
3.4 面向?qū)ο蟮奶卣?/h3>
面向?qū)ο笾饕哂腥筇卣鳎蠢^承、多態(tài)和封裝。正因?yàn)檫@些機(jī)制的存在,才使得應(yīng)用程序變得更為簡(jiǎn)單和豐富多彩。本節(jié)將對(duì)以上三個(gè)特征進(jìn)行詳細(xì)介紹,此外還會(huì)提到面向?qū)ο笾辛硪粋€(gè)重要知識(shí)點(diǎn)——重載。
3.4.1 繼承
繼承是指一個(gè)類A能利用另一個(gè)類B的資源(包括屬性和方法等),其中B類被稱為基類(或父類),而A類被稱為派生類(或子類)。繼承的使用語(yǔ)法如下所示。
public class A { public A{} } public B:A { public B{} }
類的繼承用符號(hào)“:”進(jìn)行標(biāo)識(shí),以上代碼定義了B類繼承于A類。如果B類繼承于A類,那么B類是否能訪問(wèn)A類中的全部成員?答案是否定的。這也就是下面要說(shuō)明的有關(guān)派生類在基類中的訪問(wèn)權(quán)限問(wèn)題。
(1)大多數(shù)而并非所有類都可以作為基類被繼承,比如帶有sealed修飾符的密封類不能被繼承。
(2)基類中只有兩種成員能被派生類訪問(wèn),包括public和protected類型的成員。其中,protected類型是專為派生類設(shè)計(jì)的,該類型的成員只能在派生類中進(jìn)行訪問(wèn)。
(3)在派生類中可以修改基類中的以下成員,包括虛擬成員(virtual)和抽象成員(abstract)。其中對(duì)虛擬成員的修改是在派生類中重寫該成員的執(zhí)行代碼;而對(duì)于抽象成員而言,它在基類中,沒(méi)有執(zhí)行代碼,需要在派生類中進(jìn)行添加。
可能有些讀者對(duì)于以上的講解感覺比較抽象,下面通過(guò)一個(gè)簡(jiǎn)單的例子進(jìn)行說(shuō)明。
打開VS2008,在D:\C#\ch3目錄下建立名為InheritTest的控制臺(tái)應(yīng)用程序。首先為當(dāng)前工程添加一個(gè)基類ClassF,代碼如下所示。
class ClassF { //公有字段 public string name="zhangwei"; public string age; //公有屬性 public string Age { get { return age; } set { age = value; } } //虛擬方法 public virtual double Income(double time) { double income = time * 100.0 + 2000.0; return income; } }
基類ClassF中,定義了一個(gè)公有字段,一個(gè)公有屬性和一個(gè)虛擬方法。下面是派生類ClassS的代碼。
class ClassS:ClassF { //重寫虛擬方法 public override double Income(double time) { double income = time * 100.0 + 3000.0; return income; } static void Main(string[] args) { ClassS cs = new ClassS(); Console.WriteLine("姓名:"); //繼承公有字段 Console.WriteLine(cs.name); Console.WriteLine("工齡:"); //繼承公有屬性 cs.Age= Console.ReadLine(); Console.WriteLine("工資:"); //繼承虛擬方法 Console.WriteLine(cs.Income(Convert.ToDouble(cs.Age)).ToString()); Console.ReadKey(); } }
在派生類ClassS中,調(diào)用了ClassF類中的公有字段name、公有屬性Age并重寫了虛擬方法Income()。此處,需要注意的是重寫虛擬方法需要用到override關(guān)鍵字。運(yùn)行程序,結(jié)果如圖3-23所示。

圖3-23 運(yùn)行結(jié)果
3.4.2 多態(tài)
多態(tài)是面向?qū)ο蟮挠忠粋€(gè)重要特征,它主要是指同一操作(如方法)作用于不同的類的實(shí)例,將產(chǎn)生不同的結(jié)果。多態(tài)主要是通過(guò)在派生類中對(duì)基類中的成員進(jìn)行替換或重定義完成。下面通過(guò)例子進(jìn)行說(shuō)明。
打開VS2008,在D:\C#\ch3目錄下建立名為PolymorphismTest的控制臺(tái)應(yīng)用程序。打開工程,添加如下代碼。
//基類 class ClassF { public virtual void Out() { Console.WriteLine("調(diào)用了基類中的方法!"); } } //派生類1 class ClassS1:ClassF { public override void Out() { Console.WriteLine("調(diào)用了派生類1中的方法!"); } } //派生類2 class ClassS2:ClassF { public override void Out() { Console.WriteLine("調(diào)用了派生類2中的方法!"); } } //輸出結(jié)果 class Test { static void Main(string[] args) { ClassF[] cf = new ClassF[3]; cf[0] = new ClassF(); cf[1] = new ClassS1(); cf[2] = new ClassS2(); foreach (ClassF c in cf) { c.Out(); } Console.ReadKey(); } }
上面代碼演示了多態(tài)性的實(shí)現(xiàn)過(guò)程,通過(guò)在兩個(gè)派生類中重寫基類中的虛方法實(shí)現(xiàn)。運(yùn)行結(jié)果如圖3-24所示。

圖3-24 運(yùn)行結(jié)果
如果要在派生類中隱藏基類中的非虛成員,可以使用new關(guān)鍵字。代碼如下所示。
class ClassF { public void Out() { Console.WriteLine("調(diào)用了基類中的方法!"); } } class ClassS1:ClassF { public new void Out() { Console.WriteLine("調(diào)用了派生類1中的方法!"); } } class Test { static void Main(string[] args) { ClassS1 cs = new ClassS1(); Console.WriteLine(cs.Out().ToString()); //調(diào)用派生類中的方法 Console.WriteLine(((ClassF)cs).Out().ToString()); //調(diào)用基類中的方法 Console.ReadKey(); } }
運(yùn)行結(jié)果如圖3-25所示。

圖3-25 運(yùn)行結(jié)果
上面代碼同樣也實(shí)現(xiàn)了多態(tài)的功能。多態(tài)本身理論比較難,本節(jié)僅通過(guò)兩個(gè)例子對(duì)簡(jiǎn)單的多態(tài)應(yīng)用進(jìn)行了說(shuō)明,多態(tài)的主要作用是提高代碼的重用性和簡(jiǎn)化程序結(jié)構(gòu)。
3.4.3 封裝
封裝是指將對(duì)象的信息進(jìn)行隱藏,只是提供一個(gè)訪問(wèn)接口,使它的使用者無(wú)法看到對(duì)象的具體信息。在類中,通過(guò)不同的修飾符能讓類的成員實(shí)現(xiàn)公開或隱藏。通過(guò)這些修飾符,類實(shí)現(xiàn)了很好的封裝。封裝的主要用途是防止數(shù)據(jù)受到意外的破壞,代碼如下所示。
class Test { private int a; public int wr() { return a; } public void rd(int value) { a = value; } } class Program { static void Main(string[] args) { Test ts = new Test(); ts.rd(3); ts.wr(); } }
上面的代碼中,使Test類中的私有字段被訪問(wèn),但又很好地保護(hù)了它的數(shù)據(jù)不被破壞。封裝的內(nèi)容遠(yuǎn)不止這些,但基本思想是一致的。讀者應(yīng)該注意對(duì)封裝思想的學(xué)習(xí),這樣才能很好地應(yīng)用封裝的操作。
3.4.4 重載
重載是面向?qū)ο笾谐筇卣魍獾挠忠粋€(gè)重要知識(shí)點(diǎn),它是指在類中同名成員的不同定義。它的主要作用是使程序邏輯更加清晰。重載主要包括方法重載和運(yùn)算符重載,本節(jié)將通過(guò)例子對(duì)這兩者進(jìn)行詳細(xì)介紹。
3.4.5 方法重載
方法重載是C#中運(yùn)用最廣泛的一種重載方式,它是指在類中建立名稱相同但參數(shù)不同的方法。方法重載主要是為了解決操作同一類對(duì)象需要使用不同方法的問(wèn)題,如計(jì)算一類圖形的面積。圖形中包括矩形、圓和橢圓,它們的面積計(jì)算公式是不同的,這里就需要用到重載的概念。下面舉例進(jìn)行說(shuō)明。
打開VS2008,在D:\C#\ch3目錄下建立名為Overload1Test的控制臺(tái)應(yīng)用程序。打開工程,添加如下代碼。
class Area { //計(jì)算矩形面積 public int Count(int x, int y) { return x * y; } //計(jì)算圓面積 public double Count(double r) { return Math.PI * r * r; } //計(jì)算橢圓面積 public double Count(double a, double b) { return Math.PI * a * b; } static void Main(string[] args) { Area area =new Area(); Console.WriteLine("矩形面積為:" + area.Count(4, 6)); Console.WriteLine("圓的面積為:"+area.Count(3.4)); Console.WriteLine("橢圓的面積為:"+area.Count(2.5,3.6)); Console.ReadKey(); } }

圖3-26 運(yùn)行結(jié)果
在Area類中分別定義了計(jì)算三種圖形面積的方法,三種方法具有相同的名稱,不同的參數(shù)和返回類型,實(shí)現(xiàn)了方法的重載。程序運(yùn)行結(jié)果如圖3-26所示。
3.4.6 運(yùn)算符重載
運(yùn)算符重載主要是為了在類中擴(kuò)展運(yùn)算符的功能,以完成一些特殊的操作。重載運(yùn)算符需要用到operator關(guān)鍵字。下面通過(guò)例子進(jìn)行說(shuō)明。
打開VS2008,在D:\C#\ch3目錄下建立名為Overload2test的控制臺(tái)應(yīng)用程序。打開工程,添加如下代碼。
class Test { public int real; public int img; public Test(int real, int img) { this.real = real; this.img = img; } public static Test operator +(Test x, Test y) { return new Test(x.real+y.real, x.img+y.img); } static void Main(string[] args) { Test t1 = new Test(2,3); Test t2 = new Test(4,5); Test t3 = t1 + t2; Console.WriteLine("該復(fù)數(shù)的實(shí)部為:" + t3.real); Console.WriteLine("該復(fù)數(shù)的虛部為:" + t3.img); Console.ReadKey(); } }
這是一個(gè)實(shí)現(xiàn)復(fù)數(shù)加法的經(jīng)典例子,通過(guò)在Test類中重載“+”運(yùn)算符實(shí)現(xiàn)了復(fù)數(shù)的加法。運(yùn)行結(jié)果如圖3-27所示。

圖3-27 運(yùn)行結(jié)果
在運(yùn)算符重載的使用過(guò)程中,應(yīng)注意以下情況。
(1)并非所有運(yùn)算符都能被重載,不能被重載的運(yùn)算符包括“=”、“? :”、“->”、“new”、“is”、“sizeof”和“typeof”。
(2)重載運(yùn)算符不能改變?cè)瓉?lái)運(yùn)算符的優(yōu)先級(jí)和操作數(shù)。
(3)比較運(yùn)算符必須成對(duì)重載,如“==”和“! =”, “>”和“<”等。
(4)重載運(yùn)算符可由派生類繼承。
3.5 接口
接口是面向?qū)ο笾械挠忠粋€(gè)重要概念,它用于定義類或結(jié)構(gòu)的行為特征。接口包含事件、方法、屬性和索引器4種成員,它只包含這些成員的簽名而不包含實(shí)現(xiàn),這一點(diǎn)和抽象類比較相似;而且接口不能包含字段,且它的所有成員都必須是公開的。
3.5.1 接口的聲明
接口的聲明需要采用interface關(guān)鍵字,如下所示。
interface MyInterface { void MyMethod(); string MyProperty { get; } }
在接口MyInterface中,定義了一個(gè)方法成員和一個(gè)屬性。細(xì)心的讀者可能會(huì)發(fā)現(xiàn)以上定義中,接口成員沒(méi)有采用修飾符,如果試圖添加任何修飾符,均會(huì)出現(xiàn)“修飾符無(wú)效”的錯(cuò)誤。因?yàn)樵诮涌诘亩x中規(guī)定了所有接口成員必須是公開的。
3.5.2 接口的使用
前面提到,接口只能包含成員的簽名,不能包含成員的實(shí)現(xiàn)。接口成員必須要在繼承該接口中的類中才能實(shí)現(xiàn)。下面對(duì)MyInterface接口中的MyMethod()方法進(jìn)行實(shí)現(xiàn),代碼如下所示。
class Program:Interface1 { public void MyMethod() { Console.WriteLine("實(shí)現(xiàn)了該接口的方法!"); } static void Main(string[] args) { Program pg = new Program(); pg.MyMethod(); Console.ReadKey(); } }
運(yùn)行結(jié)果,如圖3-28所示。

圖3-28 運(yùn)行結(jié)果
上面代碼中,實(shí)現(xiàn)了接口MyInterface中的MyMethod()方法并完成輸出。在使用接口時(shí),應(yīng)注意以下問(wèn)題。
(1)接口自身不能被實(shí)例化,需要在繼承它的類中才能使用。
(2)接口不能包含字段。
(3)接口不能包含靜態(tài)成員。
(4)接口成員默認(rèn)是public類型的,不能在接口成員前面加任何修飾符。
(5)類和結(jié)構(gòu)可以從多個(gè)接口繼承。
(6)接口本身也可以從其他接口繼承,它的繼承機(jī)制和類的繼承機(jī)制一樣。
3.6 面向?qū)ο蟮钠渌黝}
本章前面部分以類為重點(diǎn)介紹了面向?qū)ο蟮南嚓P(guān)知識(shí),但僅有類是不夠的,面向?qū)ο筮€有一些其他主題,比如命名空間等。在本節(jié)中,將對(duì)面向?qū)ο笾衅渌恍┲黝}進(jìn)行介紹,以幫助讀者更好地理解面向?qū)ο蟮谋举|(zhì)。
3.6.1 命名空間
在.NET Framework中,一個(gè)命名空間就是一個(gè)邏輯的命名系統(tǒng),它用于指定一個(gè)范圍,并在該范圍組織代碼(包括類、接口、結(jié)構(gòu)體和枚舉等)。命名空間在前面的代碼中已經(jīng)多次用到,如果需要使用包含在命名空間中的類,則需要使用using指令包含該命名空間,如下所示。
using System; …… Console.WriteLine("命名空間的用法!");
System是命名空間,Console是該命名空間中的一個(gè)類。因?yàn)榘薙ystem命名空間,所以才能使用它里面的類。同樣,也可以用如下方式訪問(wèn)Console類,如下所示。
System.Console.WriteLine("命名空間的用法!");
這里直接使用了顯示的命名空間前綴來(lái)完成Console類的訪問(wèn)。這是一種不推崇的方法,因?yàn)樗鼤?huì)增加代碼的復(fù)雜性。命名空間前面不能加任何修飾符,它的關(guān)鍵字是namespace。在命名空間的內(nèi)部,也可以包含命名空間,稱為命名空間的嵌套,如下所示。
namespace NameSpaceA { namespace NameSpaceB { class Program { } } }
NameSpaceB嵌套在NameSpaceA命名空間中,下面為等效代碼。
namespace NameSpaceA.NameSpaceB { class Program { } }
如果一個(gè)命名空間的名字很長(zhǎng),但又必須要使用多次,.NET Framwork中提供了一種命名空間別名的方式來(lái)簡(jiǎn)化。如下所示。
using ns=NameSpaceName;
在需要使用該命名空間的地方,可以直接用ns代替。為了幫助讀者能更好地理解命名空間的用法,下面給出一個(gè)完整的例子進(jìn)行說(shuō)明,代碼如下所示。
using nsp = NameSpaceA.NameSpaceB.NameSpaceC; //使用命名空間別名 //定義嵌套命名空間 namespace NameSpaceA { namespace NameSpaceB { namespace NameSpaceC { public class cs { public void output() { Console.WriteLine("命名空間的學(xué)習(xí)!"); } } } } } //調(diào)用嵌套命名空間中的類成員 namespace ns { class Program { static void Main(string[] args) { nsp.cs c = new nsp.cs(); c.output(); Console.ReadKey(); } } }
上面的代碼主要實(shí)現(xiàn)了命名空間的嵌套,命名空間的別名及使用命名空間中包含的類成員,運(yùn)行結(jié)果如圖3-29所示。

圖3-29 運(yùn)行結(jié)果
3.6.2 程序集
程序集是.NET Framework應(yīng)用程序的基本構(gòu)造塊,當(dāng)生成C#應(yīng)用程序時(shí),VS會(huì)在當(dāng)前工程的Debug目錄下生成可移植可執(zhí)行的文件,通常是.exe或.dll文件。在較大的項(xiàng)目中,程序集的作用是十分明顯的。項(xiàng)目經(jīng)理可以把項(xiàng)目劃分成幾個(gè)單獨(dú)的模塊,由不同的人員進(jìn)行開發(fā),然各自生成程序集,最后通過(guò)一定的方式將這些程序集組合起來(lái)即可。
程序集具有以下特點(diǎn)。
(1)程序集以.exe或.dll格式的文件存在。
(2)能在多個(gè)應(yīng)用程序之間實(shí)現(xiàn)程序集的共享。
(3)在單個(gè)應(yīng)用程序中可以使用程序集的兩個(gè)版本。
3.6.3 類庫(kù)
在.NET Framework中,類庫(kù)是由命名空間組成,同時(shí)又是類、接口和值類型組成的庫(kù),這些庫(kù)能對(duì)系統(tǒng)功能進(jìn)行訪問(wèn),是建立.NET Framework應(yīng)用程序、組件和控件的基礎(chǔ)。.NET Framework中包含了大量的系統(tǒng)類庫(kù)供用戶使用,調(diào)用這些類庫(kù)時(shí),系統(tǒng)會(huì)自動(dòng)添加,只需用using指令包含類庫(kù)提供的命名空間即可,比如前面經(jīng)常使用的System命名空間。
但系統(tǒng)提供的類庫(kù)有時(shí)候并不能完全滿足用戶的要求,此時(shí)就需要自定義類庫(kù)。下面通過(guò)例子說(shuō)明類庫(kù)的編寫和調(diào)用。
打開VS2008,在D:\C#\ch3目錄下建立名為ClassLibraryTest的類庫(kù)程序。打開工程,添加如下代碼。
namespace ClassLibraryTest { public class Test { public int Add(int x, int y) { return x + y; } public int Dec(int x, int y) { return x - y; } public int mul(int x, int y) { return x * y; } public int dev(int x, int y) { return x / y; } } }
在ClassLibraryTest命名空間的Test類中定義了4個(gè)方法,分別用于計(jì)算兩個(gè)整數(shù)加、減、乘和除的結(jié)果。選擇“生成”—“生成解決方案”命令,或者按F6鍵將以上代碼生成類庫(kù)。此時(shí)轉(zhuǎn)到當(dāng)前工程的Debug目錄下,可以看到名為ClassLibraryTest.dll的動(dòng)態(tài)鏈接庫(kù)文件。下面需要做的工作是調(diào)用該類庫(kù),主要分為以下幾個(gè)步驟。
(1)打開VS2008,在D:\C#\ch3目錄下建立名為ClTest的控制臺(tái)應(yīng)用程序,打開工程,首先需要對(duì)該類庫(kù)進(jìn)行引用。選擇“項(xiàng)目”—“添加引用”—“瀏覽”標(biāo)簽,轉(zhuǎn)到該類庫(kù)工程的Debug目錄,如圖3-30所示。

圖3-30 添加引用
(2)轉(zhuǎn)到“解決方案資源管理器”界面上,可以看到該類庫(kù)已經(jīng)被添加,如圖3-31所示。

圖3-31 添加類庫(kù)
(3)需要包含該類庫(kù)中的命名空間,如下所示。
using ClassLibraryTest;
(4)在當(dāng)前工程中添加如下代碼。
namespace Cltest { class Program { static void Main(string[] args) { Test ts = new Test(); Console.WriteLine("兩個(gè)數(shù)相加的結(jié)果為:" + ts.Add(6, 3)); Console.WriteLine("兩個(gè)數(shù)相減的結(jié)果為:" + ts.Dec(6, 3)); Console.WriteLine("兩個(gè)數(shù)相乘的結(jié)果為:" + ts.mul(6, 3)); Console.WriteLine("兩個(gè)數(shù)相除的結(jié)果為:" + ts.dev(6, 3)); Console.ReadKey(); } } }
(5)運(yùn)行程序,結(jié)果如圖3-32所示。

圖3-32 運(yùn)行結(jié)果
3.7 小結(jié)
本章主要介紹了面向?qū)ο蠹夹g(shù)的基本內(nèi)容。首先是類的相關(guān)知識(shí)的介紹,類是面向?qū)ο蠹夹g(shù)中最基礎(chǔ)也是最重要的內(nèi)容,本章分別從類的定義、類的訪問(wèn)權(quán)限和類的成員等方面對(duì)類的用法進(jìn)行了說(shuō)明。其中采用public、private、protected和abstract等修飾符設(shè)置了類的不同訪問(wèn)權(quán)限;類的成員包括常量、字段、屬性、索引器、方法和事件等,本章通過(guò)例子對(duì)以上成員進(jìn)行了詳細(xì)的說(shuō)明。接下來(lái)介紹了面向?qū)ο蟮娜筇卣鳌^承、多態(tài)和封裝,它們是面向?qū)ο蠹夹g(shù)的核心部分。在有關(guān)接口的內(nèi)容中簡(jiǎn)單介紹了接口的聲明和使用。最后介紹了面向?qū)ο蠹夹g(shù)中的其他一些主題,包括命名空間、程序集和類庫(kù)等。
- Unreal Engine:Game Development from A to Z
- Internet接入·網(wǎng)絡(luò)安全
- Dreamweaver CS3+Flash CS3+Fireworks CS3創(chuàng)意網(wǎng)站構(gòu)建實(shí)例詳解
- R Data Mining
- Photoshop CS3圖像處理融會(huì)貫通
- Storm應(yīng)用實(shí)踐:實(shí)時(shí)事務(wù)處理之策略
- Docker on Amazon Web Services
- Practical Big Data Analytics
- Applied Data Visualization with R and ggplot2
- 網(wǎng)管員世界2009超值精華本
- PostgreSQL High Performance Cookbook
- 軟件測(cè)試設(shè)計(jì)
- Mastering Android Game Development with Unity
- 傳感器與檢測(cè)技術(shù)
- 數(shù)字中國(guó):大數(shù)據(jù)與政府管理決策