




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第6章面向?qū)ο蟪绦蛟O(shè)計(jì)
6.1面向?qū)ο蟪绦蛟O(shè)計(jì)概述6.2命名空間6.3類(lèi)6.4對(duì)象6.5構(gòu)造函數(shù)和析構(gòu)函數(shù)6.6靜態(tài)成員6.7屬性6.8方法6.9索引器6.10委托6.11事件6.12運(yùn)算符重載6.13類(lèi)的轉(zhuǎn)換6.1面向?qū)ο蟪绦蛟O(shè)計(jì)概述6.1.1面向?qū)ο蟮幕靖拍铑?lèi)和對(duì)象屬性、方法和事件封裝繼承重載與重寫(xiě)6.1.2面向?qū)ο蟮膬?yōu)點(diǎn)維護(hù)簡(jiǎn)單。可擴(kuò)充性。代碼重用。6.2命名空間6.2.1命名空間概述在.NET中,類(lèi)是通過(guò)命名空間(namespace)來(lái)組織的。命名空間提供了可以將類(lèi)分成邏輯組的方法,將系統(tǒng)中的大量類(lèi)庫(kù)有序地組織起來(lái),使得類(lèi)更容易使用和管理。可以將命名空間想像成文件夾,類(lèi)的文件夾就是命名空間,不同的命名空間內(nèi),可以定義許多類(lèi)。在每個(gè)命名空間下,所有的類(lèi)都是“獨(dú)立”且“唯一”的。6.2.2使用命名空間
在C#中,使用命名空間有兩種方式,一種是明確指出命名空間的位置,另一種是通過(guò)using關(guān)鍵字引用命名空間。直接定位在應(yīng)用程序中,任何一個(gè)命名空間都可以在代碼中直接使用。例如:System.Console.WriteLine("ABC");這個(gè)語(yǔ)句是調(diào)用了System命名空間中Console類(lèi)的WriteLine方法。1)使用using關(guān)鍵字在應(yīng)用程序中要使用一個(gè)命名空間,還可以采取引用命名空間的方法,在引用后,應(yīng)用程序中就可使用該命名空間內(nèi)的任一個(gè)類(lèi)了。引用命名空間的方法是利用using關(guān)鍵字,其使用格式如下:
using[別名=]命名空間或
using[別名=]命名空間.成員2)自定義命名空間在C#中,除了使用系統(tǒng)的命名空間外,還可以在應(yīng)用程序中自已聲明命名空間。其使用語(yǔ)法格式如下:namespace命名空間名稱{命名空間定義體}其中,“命名空間名稱”指出命名空間的唯一名稱,必須是有效的C#標(biāo)識(shí)符。例如,在應(yīng)用程序中自定義Ns1命名空間:namespaceNs1{ classA{…} classB{…}}6.3類(lèi)6.3.1類(lèi)的聲明類(lèi)的聲明語(yǔ)法格式如下:[類(lèi)的修飾符]class類(lèi)名[:基類(lèi)名]{//類(lèi)的成員;}[;]類(lèi)的修飾符說(shuō)明public公有類(lèi)。表示不受限制對(duì)該類(lèi)的訪問(wèn)。protected保護(hù)類(lèi)。表示只能從所在類(lèi)和所在類(lèi)派生的子類(lèi)進(jìn)行訪問(wèn)。internal內(nèi)部類(lèi)。只有其所在類(lèi)才能訪問(wèn)。private私有類(lèi)。只有該類(lèi)才能訪問(wèn)。abstract抽象類(lèi)。表示該類(lèi)是一個(gè)不完整的類(lèi),不允許建立類(lèi)的實(shí)例。sealed密封類(lèi)。不允許從該類(lèi)派生新的類(lèi)。例如,以下聲明了一個(gè)Person類(lèi):publicclassPerson{ publicintpno; //編號(hào) publicstringpname; //姓名 publicvoidsetdata(intno,stringname) { pno=no;pname=name; } publicvoiddispdata() { Console.WriteLine("{0}{1}",pno,pname); }}6.3.2類(lèi)的成員類(lèi)的成員說(shuō)明字段字段存儲(chǔ)類(lèi)要滿足其設(shè)計(jì)所需要的數(shù)據(jù),亦稱為數(shù)據(jù)成員。屬性屬性是類(lèi)中可以像類(lèi)中的字段一樣被訪問(wèn)的方法。屬性可以為類(lèi)字段提供保護(hù),避免字段在對(duì)象不知道的情況下被更改。方法方法定義類(lèi)可以執(zhí)行的操作。方法可以接受提供輸入數(shù)據(jù)的參數(shù),并且可以通過(guò)參數(shù)返回輸出數(shù)據(jù)。方法還可以不使用參數(shù)而直接返回值。事件事件是向其他對(duì)象提供有關(guān)事件發(fā)生(如單擊按鈕或成功完成某個(gè)方法)通知的一種方式。索引器索引器允許以類(lèi)似于數(shù)組的方式為對(duì)象建立索引。運(yùn)算符運(yùn)算符是對(duì)操作數(shù)執(zhí)行運(yùn)算的術(shù)語(yǔ)或符號(hào),如+、*、<等。構(gòu)造函數(shù)構(gòu)造函數(shù)是在第一次創(chuàng)建對(duì)象時(shí)調(diào)用的方法。它們通常用于初始化對(duì)象的數(shù)據(jù)。析構(gòu)函數(shù)析構(gòu)函數(shù)是當(dāng)對(duì)象即將從內(nèi)存中移除時(shí)由運(yùn)行庫(kù)執(zhí)行引擎調(diào)用的方法。它們通常用來(lái)確保需要釋放的所有資源都得到了適當(dāng)?shù)奶幚怼n?lèi)成員的修飾符說(shuō)明public公有成員。提供了類(lèi)的外部界面,允許類(lèi)的使用者從外部進(jìn)行訪問(wèn),這是限制最少的一種訪問(wèn)方式。private私有成員(默認(rèn)的)。僅限于類(lèi)中的成員可以訪問(wèn),從類(lèi)的外部訪問(wèn)私有成員是不合法的,如果在聲明中沒(méi)有出現(xiàn)成員的訪問(wèn)修飾符,按照默認(rèn)方式成員為私有的。protected保護(hù)成員。這類(lèi)成員不允許外部訪問(wèn),但允許其派生類(lèi)成員訪問(wèn)。internal內(nèi)部成員。允許同一個(gè)命名空間中的類(lèi)訪問(wèn)。readonly只讀成員。這類(lèi)成員的值只能讀,不能寫(xiě)。也就是說(shuō),除了賦予初始值外,在程序的任何部分將無(wú)法更改這個(gè)成員的值。6.3.3分部類(lèi)分部類(lèi)可以將類(lèi)(結(jié)構(gòu)或接口等)的聲明拆分到兩個(gè)或多個(gè)源文件中。若要拆分類(lèi)的代碼,被拆分類(lèi)的每一部分的定義前邊都要用partial關(guān)鍵字修飾。分部類(lèi)的每一部分都可以存放在不同的文件中,編譯時(shí)會(huì)自動(dòng)將所有部分組合起來(lái)構(gòu)成一個(gè)完整的類(lèi)聲明。6.4對(duì)象
6.4.1定義類(lèi)的對(duì)象一旦聲明了一個(gè)類(lèi),就可以用它作為數(shù)據(jù)類(lèi)型來(lái)定義類(lèi)對(duì)象(簡(jiǎn)稱為對(duì)象)。定義類(lèi)的對(duì)象分以下兩步:1)定義對(duì)象引用其語(yǔ)法格式如下:類(lèi)名對(duì)象名;例如,以下語(yǔ)句定義Person類(lèi)的對(duì)象引用p:Personp;2)創(chuàng)建類(lèi)的實(shí)例其語(yǔ)法格式如下:對(duì)象名=new類(lèi)名();例如,以下語(yǔ)句創(chuàng)建Person類(lèi)的對(duì)象實(shí)例:p=newPersone();以上兩步也可以合并成一步。其語(yǔ)法格式如下:類(lèi)名對(duì)象名=new類(lèi)名();例如:Personp=newPerson();理解對(duì)象引用和類(lèi)實(shí)例的區(qū)別。兩個(gè)對(duì)象引用可以引用同一個(gè)對(duì)象,例如:Personp1=newPerson();Personp2=p1;p1p26.4.2訪問(wèn)對(duì)象的字段訪問(wèn)對(duì)象字段的語(yǔ)法格式如下:對(duì)象名.字段名其中,“.”是一個(gè)運(yùn)算符,該運(yùn)算符的功能是表示對(duì)象的成員。例如,前面定義的p對(duì)象的成員變量表示為:p.pno,p.pname6.4.3調(diào)用對(duì)象的方法調(diào)用對(duì)象的方法的語(yǔ)法格式如下:對(duì)象名.方法名(參數(shù)表)例如,調(diào)用前面定義的p對(duì)象的成員方法setdata為:p.setdata(101,"Mary");【例6.1】設(shè)計(jì)一個(gè)控制臺(tái)應(yīng)用程序,說(shuō)明調(diào)用對(duì)象方法的過(guò)程。usingSystem;namespaceProj6_1{publicclassTPoint//聲明類(lèi)TPoint{intx,y;//類(lèi)的私有字段publicvoidsetpoint(intx1,inty1){ x=x1;y=y1;}publicvoiddispoint(){Console.WriteLine("({0},{1})",x,y);}}classProgram{staticvoidMain(string[]args){TPointp1=newTPoint(); //定義對(duì)象p1 p1.setpoint(2,6); Console.Write("第一個(gè)點(diǎn)=>"); p1.dispoint(); TPointp2=newTPoint(); //定義對(duì)象p2 p2.setpoint(8,3); Console.Write("第二個(gè)點(diǎn)=>"); p2.dispoint();}}}6.5構(gòu)造函數(shù)和析構(gòu)函數(shù)6.5.1構(gòu)造函數(shù)1.什么是構(gòu)造函數(shù)構(gòu)造函數(shù)是在創(chuàng)建給定類(lèi)型的對(duì)象時(shí)執(zhí)行的類(lèi)方法。構(gòu)造函數(shù)具有如下性質(zhì):構(gòu)造函數(shù)的名稱與類(lèi)的名稱相同。構(gòu)造函數(shù)盡管是一個(gè)函數(shù),但沒(méi)有任何類(lèi)型,即它既不屬于返回值函數(shù)也不屬于void函數(shù)。一個(gè)類(lèi)可以有多個(gè)構(gòu)造函數(shù),但所有構(gòu)造函數(shù)的名稱都必須相同,它們的參數(shù)各不相同,即構(gòu)造函數(shù)可以重載。當(dāng)類(lèi)對(duì)象創(chuàng)建時(shí),構(gòu)造函數(shù)會(huì)自動(dòng)地執(zhí)行;由于它們沒(méi)有返回類(lèi)型,因此不能像其他函數(shù)那樣進(jìn)行調(diào)用。當(dāng)類(lèi)對(duì)象聲明時(shí),調(diào)用哪一個(gè)構(gòu)造函數(shù)取決于傳遞給它的參數(shù)類(lèi)型。構(gòu)造函數(shù)不能被繼承。2.調(diào)用構(gòu)造函數(shù)當(dāng)定義類(lèi)對(duì)象時(shí),構(gòu)造函數(shù)會(huì)自動(dòng)執(zhí)行。1)調(diào)用默認(rèn)構(gòu)造函數(shù)不帶參數(shù)的構(gòu)造函數(shù)稱為默認(rèn)構(gòu)造函數(shù)。無(wú)論何時(shí),只要使用new運(yùn)算符實(shí)例化對(duì)象,并且不為new提供任何參數(shù),就會(huì)調(diào)用默認(rèn)構(gòu)造函數(shù)。假設(shè)一個(gè)類(lèi)包含有默認(rèn)構(gòu)造函數(shù),調(diào)用默認(rèn)構(gòu)造函數(shù)的語(yǔ)法如下:類(lèi)名對(duì)象名=new類(lèi)名();如果沒(méi)有為對(duì)象提供構(gòu)造函數(shù),則默認(rèn)情況下C#將創(chuàng)建一個(gè)構(gòu)造函數(shù),該構(gòu)造函數(shù)實(shí)例化對(duì)象,并將所有成員變量設(shè)置為相應(yīng)的默認(rèn)值。2)調(diào)用帶參數(shù)的構(gòu)造函數(shù)假設(shè)一個(gè)類(lèi)中包含有帶參數(shù)的構(gòu)造函數(shù),調(diào)用這種帶參數(shù)的構(gòu)造函數(shù)的語(yǔ)法如下:類(lèi)名對(duì)象名=new類(lèi)名(參數(shù)表);【例6.2】設(shè)計(jì)一個(gè)控制臺(tái)應(yīng)用程序,說(shuō)明調(diào)用構(gòu)造函數(shù)的過(guò)程。namespaceProj6_2{classProgram{publicclassTPoint1 //聲明類(lèi)TPoint1{ intx,y; //類(lèi)的私有變量 publicTPoint1(){} //默認(rèn)的構(gòu)造函數(shù) publicTPoint1(intx1,inty1) //帶參數(shù)的構(gòu)造函數(shù) {x=x1;y=y1;} publicvoiddispoint() {Console.WriteLine("({0},{1})",x,y);} } staticvoidMain(string[]args) {TPoint1p1=newTPoint1(); //調(diào)用默認(rèn)的構(gòu)造函數(shù) Console.Write("第一個(gè)點(diǎn)=>"); p1.dispoint(); TPoint1p2=newTPoint1(8,3);//調(diào)用帶參數(shù)的構(gòu)造函數(shù) Console.Write("第二個(gè)點(diǎn)=>"); p2.dispoint(); }}}6.5.2析構(gòu)函數(shù)1.什么是析構(gòu)函數(shù)在對(duì)象不再需要時(shí),希望確保它所占的存儲(chǔ)空間能被收回。C#中提供了析構(gòu)函數(shù)用于專(zhuān)門(mén)釋放被占用的系統(tǒng)資源。析構(gòu)函數(shù)具有如下性質(zhì):析構(gòu)函數(shù)在類(lèi)對(duì)象銷(xiāo)毀時(shí)自動(dòng)執(zhí)行。一個(gè)類(lèi)只能有一個(gè)析構(gòu)函數(shù),而且析構(gòu)函數(shù)沒(méi)有參數(shù),即析構(gòu)函數(shù)不能重載。析構(gòu)函數(shù)的名稱是“~”加上類(lèi)的名稱(中間沒(méi)有空格)。與構(gòu)造函數(shù)一樣,析構(gòu)函數(shù)也沒(méi)有返回類(lèi)型。析構(gòu)函數(shù)不能被繼承。2.調(diào)用析構(gòu)函數(shù)當(dāng)一個(gè)對(duì)象被系統(tǒng)銷(xiāo)毀時(shí)自動(dòng)調(diào)用類(lèi)的析構(gòu)函數(shù)。【例6.3】設(shè)計(jì)一個(gè)控制臺(tái)應(yīng)用程序,說(shuō)明調(diào)用析構(gòu)函數(shù)的過(guò)程。usingSystem;namespaceProj6_3{classProgram{publicclassTPoint2//聲明類(lèi)TPoint2{ intx,y; publicTPoint2(intx1,inty1) //帶參數(shù)的構(gòu)造函數(shù) {x=x1;y=y1;} ~TPoint2() {Console.WriteLine("點(diǎn)=>({0},{1})",x,y);}}staticvoidMain(string[]args){ TPoint2p1=newTPoint2(2,6); TPoint2p2=newTPoint2(8,3);}}}6.6靜態(tài)成員6.6.1靜態(tài)字段靜態(tài)字段是類(lèi)中所有對(duì)象共享的成員,而不是某個(gè)對(duì)象的成員,也就是說(shuō)靜態(tài)字段的存儲(chǔ)空間不是放在每個(gè)對(duì)象中,而是和方法一樣放在類(lèi)公共區(qū)中。對(duì)靜態(tài)字段的操作和一般字段一樣,定義為私有的靜態(tài)字段不能被外界訪問(wèn)。靜態(tài)字段的使用方法如下:(1)靜態(tài)字段的定義與一般字段相似,但前面要加上static關(guān)鍵詞。(2)在訪問(wèn)靜態(tài)字段時(shí)采用如下格式:類(lèi)名.靜態(tài)字段名6.6.2靜態(tài)方法靜態(tài)方法與靜態(tài)字段類(lèi)似,也是從屬于類(lèi),都是類(lèi)的靜態(tài)成員。只要類(lèi)存在,靜態(tài)方法就可以使用,靜態(tài)方法的定義是在一般方法定義前加上static關(guān)鍵字。調(diào)用靜態(tài)方法的格式如下:類(lèi)名.靜態(tài)方法名(參數(shù)表);注意:靜態(tài)方法只能訪問(wèn)靜態(tài)字段、其他靜態(tài)方法和類(lèi)以外的函數(shù)及數(shù)據(jù),不能訪問(wèn)類(lèi)中的非靜態(tài)成員(因?yàn)榉庆o態(tài)成員只有對(duì)象存在時(shí)才有意義)。但靜態(tài)字段和靜態(tài)方法可由任意訪問(wèn)權(quán)限許可的成員訪問(wèn)。6.7屬性6.7.1什么是屬性屬性描述了對(duì)象的具體特性,它提供了對(duì)類(lèi)或?qū)ο蟪蓡T的訪問(wèn)。C#中的屬性更充分地體現(xiàn)了對(duì)象的封裝性,屬性不直接操作類(lèi)的字段,而是通過(guò)訪問(wèn)器進(jìn)行訪問(wèn)。6.7.2屬性聲明屬性在類(lèi)模塊里是采用下面的方式進(jìn)行聲明的,即指定變量的訪問(wèn)級(jí)別、屬性的類(lèi)型、屬性的名稱,然后是get訪問(wèn)器或者set訪問(wèn)器代碼塊。其語(yǔ)法格式如下:修飾符數(shù)據(jù)類(lèi)型屬性名稱{get訪問(wèn)器set訪問(wèn)器}其中,修飾符有new、public、protected、internal、private、static、virtual、override和abstract?!纠?.7】設(shè)計(jì)一個(gè)控制臺(tái)應(yīng)用程序,說(shuō)明屬性的使用。usingSystem;namespaceProj6_7{publicclassTPoint3 //聲明類(lèi)TPoint3{intx,y;publicintpx{ get //get訪問(wèn)器 {returnx;} set //set訪問(wèn)器 {x=value;}}publicintpy{ get //get訪問(wèn)器 {returny;} set //set訪問(wèn)器 {y=value;}}};classProgram{staticvoidMain(string[]args){ TPoint3p=newTPoint3(); p.px=3;p.py=8;//屬性寫(xiě)操作 Console.WriteLine("點(diǎn)=>({0},{1})",p.px,p.py);//屬性讀操作}}}點(diǎn)=>(3,8)6.8方法
6.8.1什么是方法方法包含一系列的代碼塊。從本質(zhì)上來(lái)講,方法就是和類(lèi)相關(guān)聯(lián)的動(dòng)作,是類(lèi)的外部界面。用戶可以通過(guò)外部界面來(lái)操作類(lèi)的私有字段。6.8.2方法的定義定義方法的基本格式如下:修飾符返回類(lèi)型方法名(參數(shù)列表){ //方法的具體實(shí)現(xiàn);}6.8.3方法的返回值方法可以向調(diào)用方返回某一個(gè)特定的值。如果返回類(lèi)型不是void,則該方法可以用return關(guān)鍵字來(lái)返回值,return還可以用來(lái)停止方法的執(zhí)行。例如,以下類(lèi)MyClass3中的addnum方法用return關(guān)鍵字來(lái)返回值:publicclassMyClass3{ intnum=0; publicintaddnum(intnum1) {returnnum+num1; }}6.8.4方法的參數(shù)方法中的參數(shù)是保證不同的方法間互動(dòng)的重要橋梁,方便用戶對(duì)數(shù)據(jù)的操作。C#中方法的參數(shù)有4種類(lèi)型。1.值參數(shù)不含任何修飾符,當(dāng)利用值向方法傳遞參數(shù)時(shí),編譯程序給實(shí)參的值做一份拷貝,并且將此拷貝傳遞給該方法,被調(diào)用的方法不會(huì)修改內(nèi)存中實(shí)參的值,所以使用值參數(shù)時(shí)可以保證實(shí)際值的安全性。在調(diào)用方法時(shí),如果形參的類(lèi)型是值參數(shù)的話,調(diào)用的實(shí)參的表達(dá)式必須保證是正確的值表達(dá)式。例如,前面MyClass3類(lèi)中addnum方法中的參數(shù)就是值參數(shù)。2.引用型參數(shù)
以ref修飾符聲明的參數(shù)屬引用型參數(shù)。引用型參數(shù)本身并不創(chuàng)建新的存儲(chǔ)空間,而是將實(shí)參的存儲(chǔ)地址傳遞給形參,所以對(duì)形參的修改會(huì)影響原來(lái)實(shí)參的值。在調(diào)用方法前,引用型實(shí)參必須被初始化,同時(shí)在調(diào)用方法時(shí),對(duì)應(yīng)引用型參數(shù)的實(shí)參也必須使用ref修飾。例如:publicclassMyClass4{ intnum=0; publicvoidaddnum(intnum1,refintnum2) {num2=num+num1; }}classProgram{ staticvoidMain(string[]args) {intx=0; MyClass4s=newMyClass4(); s.addnum(5,refx); Console.WriteLine(x);//輸出:5 }}引用型參數(shù)3.輸出參數(shù)以out修飾符聲明的參數(shù)屬輸出參數(shù)。與引用型參數(shù)類(lèi)似,輸出型參數(shù)也不開(kāi)辟新的內(nèi)存區(qū)域。它與引用型參數(shù)的差別在于,調(diào)用方法前無(wú)需對(duì)變量進(jìn)行初始化。輸出型參數(shù)用于傳遞方法返回的數(shù)據(jù),out修飾符后應(yīng)跟隨與形參的類(lèi)型相同的類(lèi)型,用來(lái)聲明在方法返回后傳遞的變量經(jīng)過(guò)了初始化。例如:publicclassMyClass5{intnum=0;publicvoidaddnum(intnum1,outintnum2){num2=num+num1;}}classProgram{staticvoidMain(string[]args){ intx; MyClass5s=newMyClass5(); s.addnum(5,outx); Console.WriteLine(x);//輸出:5}}輸出型參數(shù)4.數(shù)組型參數(shù)
以params修飾符聲明的參數(shù)屬數(shù)組型參數(shù)。params關(guān)鍵字可以指定在參數(shù)數(shù)目可變處采用參數(shù)的方法參數(shù)。在方法聲明中的params關(guān)鍵字之后不允許任何其他參數(shù),并且在方法聲明中只允許一個(gè)params關(guān)鍵字。有數(shù)組型參數(shù)就不能再有ref和out修飾符。例如:publicclassMyClass6{intnum=10;publicvoidaddnum(refintsum,paramsint[]b){ sum=num; foreach(intiteminb) sum+=item;}}classProgram{staticvoidMain(string[]args){ int[]a=newint[3]{1,2,3}; intx=0; MyClass6s=newMyClass6(); s.addnum(refx,a); Console.WriteLine(x);}}數(shù)組參數(shù)傳遞2維數(shù)組可不用params6.8.5方法的重載
方法的重載是指調(diào)用同一方法名,但是使用不同的數(shù)據(jù)類(lèi)型參數(shù)或者次序不一致的參數(shù)。只要一個(gè)類(lèi)中有兩個(gè)以上的同名方法,且使用的參數(shù)類(lèi)型或者個(gè)數(shù)不同,編譯器就可以判斷在哪種情況下調(diào)用哪種方法了。為此,C#中引入了成員簽名的概念。成員簽名包含成員的名稱和參數(shù)列表,每個(gè)成員簽名在類(lèi)型中必須是唯一的,只要成員的參數(shù)列表不同,成員的名稱可以相同。如果同一個(gè)類(lèi)有兩個(gè)或多個(gè)這樣的成員(方法、屬性、構(gòu)造函數(shù)等),它們具有相同的名稱和不同的參數(shù)列表,則稱該同類(lèi)成員進(jìn)行了重載,但它們的成員簽名是不同的。例如,下面的代碼實(shí)現(xiàn)了MethodTest方法的重載(假設(shè)都是某個(gè)類(lèi)的成員),它們是不同的成員簽名:
publicintMethodTest(inti,intj) //重載方法1{ //代碼}publicintMethodTest(inti) //重載方法2{ //代碼}publicstringMethodTest(stringsr) //重載方法3{ //代碼}6.9索引器6.9.1什么是索引器索引器提供了一種訪問(wèn)類(lèi)或結(jié)構(gòu)的方法,即允許按照與數(shù)組相同的方式對(duì)類(lèi)、結(jié)構(gòu)或接口進(jìn)行索引。它的引入是為了使程序更加直觀、易于理解。例如,可以有一個(gè)大學(xué)名稱類(lèi)University,其中有一個(gè)name數(shù)組字段可能包含一些大學(xué)名稱,un是該類(lèi)的一個(gè)對(duì)象,類(lèi)中索引器允許訪問(wèn)這些大學(xué)名稱,例如:un[0]="清華大學(xué)";un[1]="北京大學(xué)";un[3]="武漢大學(xué)";6.9.2定義索引器要聲明類(lèi)或結(jié)構(gòu)上的索引器,需使用this關(guān)鍵字,其語(yǔ)法格式如下:
publicintthis[intindex]//索引器聲明{//get和set訪問(wèn)器}其中,this關(guān)鍵字引用類(lèi)的當(dāng)前實(shí)例。從中看到,索引器像對(duì)普通屬性一樣,為它提供get和set方法,這些訪問(wèn)器指定當(dāng)使用該索引器時(shí)將引用到什么內(nèi)部成員。例如,帶有索引器的University類(lèi)設(shè)計(jì)如下:publicclassUniversity{constintMAX=5;privatestring[]name=newstring[MAX];publicstringthis[intindex]//索引器{ get {if(index>=0&&index<MAX) returnname[index]; else returnname[0]; } set {if(index>=0&&index<MAX) name[index]=value; }}}6.10委托6.10.1什么是委托C++、Pascal和其他語(yǔ)言支持函數(shù)指針的概念,允許在運(yùn)行時(shí)選擇要調(diào)用的函數(shù)。Java不提供任何具有函數(shù)指針功能的結(jié)構(gòu),但C#提供這種構(gòu)造。通過(guò)使用Delegate類(lèi),委托實(shí)例可以封裝屬于可調(diào)用實(shí)體的方法。委托具有以下特點(diǎn):委托類(lèi)似于C++函數(shù)指針,但它是類(lèi)型安全的。委托允許將方法作為參數(shù)進(jìn)行傳遞。委托可用于定義回調(diào)方法。委托可以鏈接在一起。例如,可以對(duì)一個(gè)事件調(diào)用多個(gè)方法。方法不需要與委托簽名精確匹配。委托相當(dāng)于C/C++中的函數(shù)指針:函數(shù)fun1的代碼函數(shù)fun2的代碼函數(shù)fun3的代碼函數(shù)指針pfun(*pfun)(...)執(zhí)行fun1函數(shù)(*pfun)(...)執(zhí)行fun2函數(shù)(*pfun)(...)執(zhí)行fun3函數(shù)#include<stdio.h>voidf1(intx,inty,int&sum){sum=x+y;++x;++y;}voidf2(inta,intb,int&product){product=a*b;a+=b;b-=a;}voidmain(){void(*pf)(int,int,int&); /*聲明pf為函數(shù)指針*/inta=2,b=5,c;pf=f1; /*讓pf指向函數(shù)f1*/
(*pf)(a,b,c); /*通過(guò)pf調(diào)用函數(shù)f1*/
printf("%d,%d,%d\n",a,b,c);
pf=f2; /*讓pf指向函數(shù)f2*/
(*pf)(a,b,c); /*通過(guò)pf調(diào)用函數(shù)f2*/
printf("%d,%d,%d\n",a,b,c);}一個(gè)C/C++函數(shù)指針的示例6.10.2定義和使用委托定義和使用委托有3個(gè)步驟,即聲明、實(shí)例化和調(diào)用。1.聲明委托類(lèi)型聲明委托類(lèi)型就是告訴編譯器這種類(lèi)型代表了哪種類(lèi)型的方法。使用以下語(yǔ)法聲明委托類(lèi)型:[修飾符]delegate返回類(lèi)型委托類(lèi)型名(參數(shù)列表);在聲明一個(gè)委托類(lèi)型時(shí),每個(gè)委托類(lèi)型都描述參數(shù)的數(shù)目和類(lèi)型,以及它可以引用的方法的返回類(lèi)型。每當(dāng)需要一組新的參數(shù)類(lèi)型或新的返回類(lèi)型時(shí),都必須聲明一個(gè)新的委托類(lèi)型。例如:privatedelegatevoidmydelegate(intn);上述代碼聲明了一個(gè)委托mydelegate,該委托類(lèi)型可以引用一個(gè)采用int作為參數(shù)并返回void的方法。2.實(shí)例化委托聲明了委托類(lèi)型后,必須創(chuàng)建一個(gè)它的實(shí)例,即創(chuàng)建委托對(duì)象并使之與特定方法關(guān)聯(lián)。定義委托對(duì)象的語(yǔ)法格式如下:委托類(lèi)型名委托對(duì)象名;例如,以下語(yǔ)句創(chuàng)建了mydelegate委托的一個(gè)委托對(duì)象p:mydelegatep;沒(méi)有實(shí)例化另外,委托對(duì)象還需實(shí)例化為調(diào)用的方法,通常將這些方法放在一個(gè)類(lèi)中(也可以將這些方法放在程序的Program類(lèi)中),假設(shè)一個(gè)MyDeClass類(lèi)如下:classMyDeClass{ publicvoidfun1(intn) { Console.WriteLine("{0}的2倍={1}",n,2*n); } publicvoidfun2(intn) { Console.WriteLine("{0}的3倍={1}",n,3*n); }}包含委托所指向方法的類(lèi)可以通過(guò)以下語(yǔ)句實(shí)例化委托對(duì)象p:MyDeClassobj=newMyDeClass();mydelegatep=newmydelegate(obj.fun1);其中,MyDeClass類(lèi)中的fun1方法有一個(gè)int形參,其返回類(lèi)型為void,它必須與mydelegate類(lèi)型的聲明相一致。定義并實(shí)例化委托對(duì)象3.調(diào)用委托創(chuàng)建委托對(duì)象后,通常將委托對(duì)象傳遞給將調(diào)用該委托的其他代碼。通過(guò)委托對(duì)象的名稱(后面跟著要傳遞給委托的參數(shù),放在括號(hào)內(nèi))調(diào)用委托對(duì)象。其使用語(yǔ)法格式如下:委托對(duì)象名(實(shí)參列表);例如,以下語(yǔ)句調(diào)用委托p:p(100);委托對(duì)象是不可變的,即設(shè)置與它們匹配的簽名后就不能再更改簽名了。但是,如果其他方法具有同一簽名,也可以指向該方法。例如:MyDeClassobj=newMyDeClass();mydelegatep=newmydelegate(obj.fun1);p(5);p=newmydelegate(obj.fun2);p(3);【例6.9】設(shè)計(jì)一個(gè)控制臺(tái)應(yīng)用程序,說(shuō)明委托的使用。usingSystem;namespaceProj6_9{delegatedoublemydelegate(doublex,doubley);//聲明委托類(lèi)型classMyDeClass{publicdoubleadd(doublex,doubley){ returnx+y;}publicdoublesub(doublex,doubley){ returnx-y;}publicdoublemul(doublex,doubley){ returnx*y;}publicdoublediv(doublex,doubley){returnx/y;}} classProgram {staticvoidMain(string[]args) {MyDeClassobj=newMyDeClass();
mydelegatep=newmydelegate(obj.add); Console.WriteLine("5+8={0}",p(5,8)); p=newmydelegate(obj.sub); Console.WriteLine("5-8={0}",p(5,8)); p=newmydelegate(obj.mul); Console.WriteLine("5*8={0}",p(5,8)); p=newmydelegate(obj.div); Console.WriteLine("5/8={0}",p(5,8)); }}}前面代碼中p作為引用類(lèi)型,也可以改為值類(lèi)型,等價(jià)的主函數(shù)可以如下改為:
staticvoidMain(string[]args){ MyDeClassobj=newMyDeClass();
mydelegatep=obj.add; Console.WriteLine("5+8={0}",p(5,8)); p=obj.sub; Console.WriteLine("5-8={0}",p(5,8)); p=obj.mul; Console.WriteLine("5*8={0}",p(5,8)); p=obj.div; Console.WriteLine("5/8={0}",p(5,8));}可以直接把方法名賦值給委托對(duì)象來(lái)創(chuàng)建一個(gè)委托實(shí)例6.10.3委托對(duì)象封裝多個(gè)方法委托對(duì)象可以封裝多個(gè)方法,這些方法的集合稱為調(diào)用列表。委托使用“+”、“-”、“+=”和“-=”等運(yùn)算符向調(diào)用列表中增加或移除事件處理方法?!纠?.10】設(shè)計(jì)一個(gè)控制臺(tái)應(yīng)用程序,說(shuō)明委托對(duì)象封裝多個(gè)方法的使用。usingSystem;namespaceProj6_10{delegatevoidmydelegate(doublex,doubley);//聲明委托類(lèi)型classMyDeClass{publicvoidadd(doublex,doubley){ Console.WriteLine("{0}+{1}={2}",x,y,x+y);}publicvoidsub(doublex,doubley){ Console.WriteLine("{0}-{1}={2}",x,y,x-y);}publicvoidmul(doublex,doubley){Console.WriteLine("{0}*{1}={2}",x,y,x*y);}publicvoiddiv(doublex,doubley){Console.WriteLine("{0}/{1}={2}",x,y,x/y);}} classProgram {staticvoidMain(string[]args) {MyDeClassobj=newMyDeClass();
mydelegatep,a; a=obj.add; p=a;//將add方法添加到調(diào)用列表中 a=obj.sub; p+=a;//將sub方法添加到調(diào)用列表中 a=obj.mul; p+=a;//將mul方法添加到調(diào)用列表中 a=obj.div; p+=a;//將div方法添加到調(diào)用列表中 p(5,8); }}}6.10.4使委托與匿名方法關(guān)聯(lián)所謂匿名方法就是沒(méi)有方法名稱的方法。當(dāng)將委托與匿名方法關(guān)聯(lián)時(shí),直接給出方法的函數(shù)體,其一般語(yǔ)法格式如下:delegate返回類(lèi)型委托類(lèi)型名(參數(shù)列表);委托類(lèi)型名委托對(duì)象名=返回類(lèi)型(參數(shù)列表){/*匿名方法代碼*/};托對(duì)象名(實(shí)參列表)第1個(gè)語(yǔ)句聲明委托類(lèi)型;第2個(gè)語(yǔ)句定義匿名方法并將其與委托對(duì)象關(guān)聯(lián);第3個(gè)語(yǔ)句調(diào)用委托。例如,以下程序段就是使委托與匿名方法關(guān)聯(lián),并調(diào)用該委托:delegatevoidmydelegate(stringmystr);//聲明委托類(lèi)型classProgram{staticvoidMain(string[]args){mydelegatep=delegate(stringmystr){Console.WriteLine(mystr);};p("String");//輸出:String}}6.11事件6.11.1什么是事件事件是類(lèi)在發(fā)生其關(guān)注的事情時(shí)用來(lái)提供通知的一種方式。例如,封裝用戶界面控件的類(lèi)可以定義一個(gè)在用戶單擊時(shí)候發(fā)生的一個(gè)事件。控件類(lèi)不關(guān)心單擊按鈕時(shí)候發(fā)生了什么,但是它需要告知派生類(lèi)單擊事件已經(jīng)發(fā)生,然后,派生類(lèi)可以選擇如何響應(yīng)。命令按鈕用戶單擊引發(fā)執(zhí)行Click事件過(guò)程
以課堂講課為例,某教室里有若干學(xué)生,當(dāng)上課教師宣布“開(kāi)始上課”時(shí),本教室里的學(xué)生聽(tīng)到后做各種上課準(zhǔn)備,有的認(rèn)真聽(tīng)課,有的認(rèn)真看書(shū),有的做筆記,而不在本教室的學(xué)生則不會(huì)。教師開(kāi)始上課學(xué)生做某種動(dòng)作事件關(guān)聯(lián)教師類(lèi)學(xué)生類(lèi)
從程序的角度看,當(dāng)教師宣布“開(kāi)始上課”時(shí)就是發(fā)生了一個(gè)事件,是該教師通知該事件發(fā)生,所以該教師是事件源,本教室的學(xué)生(稱為訂閱者)接到通知后開(kāi)始做上課準(zhǔn)備(事件的訂閱者對(duì)事件的處理)。6.11.2事件的創(chuàng)建和使用下面介紹在C#中創(chuàng)建和使用事件的步驟。1.為事件創(chuàng)建一個(gè)委托類(lèi)型和聲明事件
在事件源類(lèi)中聲明一個(gè)事件委托類(lèi)型,該委托類(lèi)型的返回值類(lèi)型通常為void。其一般的語(yǔ)法格式如下:
delegatevoid委托類(lèi)型名([觸發(fā)事件的對(duì)象名,事件參數(shù)]);例如在課堂講課例子中,設(shè)計(jì)事件源類(lèi)為教師類(lèi)Teacher,其中通過(guò)以下語(yǔ)句聲明一個(gè)委托類(lèi)型delegateType,其委托的事件處理方法返回類(lèi)型為void,不帶任何參數(shù):
publicdelegatevoiddelegateType(); //聲明委托類(lèi)型事件是事件源類(lèi)的成員。在事件源類(lèi)中以關(guān)鍵字event聲明一個(gè)事件,其一般語(yǔ)法格式如下:
[修飾符]event委托類(lèi)型名事件名;其中,“修飾符”指出類(lèi)的用戶訪問(wèn)事件的方式,可以為public、private、protected、internal、protectedinternal、static或virtual等。例如,在Teacher類(lèi)包含以下語(yǔ)句聲明一個(gè)上課事件:publiceventdelegateTypeClassEvent; //聲明一個(gè)上課事件2.創(chuàng)建事件處理的方法
當(dāng)事件觸發(fā)時(shí)需要調(diào)用事件處理方法,需設(shè)計(jì)相應(yīng)的事件處理方法。既可以將事件處理方法放在訂閱者類(lèi)中,也可以將將事件處理方法放在單獨(dú)的類(lèi)中。例如在課堂講課例子中,設(shè)計(jì)訂閱者類(lèi)為學(xué)生類(lèi)Student,在該類(lèi)中設(shè)計(jì)以下3個(gè)事件處理方法:publicvoidListener() //聽(tīng)課方法{Console.WriteLine("學(xué)生"+sname+"正在認(rèn)真聽(tīng)課");}publicvoidRecord() //做筆記方法{Console.WriteLine("學(xué)生"+sname+"正在做筆記");}publicvoidReading() //看書(shū)方法{Console.WriteLine("學(xué)生"+sname+"正在認(rèn)真看書(shū)");}3.訂閱事件
向事件源類(lèi)的事件中添加事件處理方法中的一個(gè)委托,這個(gè)過(guò)程稱為訂閱事件,這個(gè)過(guò)程通常是在主程序中進(jìn)行的,首先必須定義一個(gè)包含事件的類(lèi)的對(duì)象,然后將事件處理方法和該對(duì)象關(guān)聯(lián)起來(lái),其格式如下:
事件類(lèi)對(duì)象名.事件名+=new委托類(lèi)型名(事件處理方法);其中,還可以使用“-=”、“+”、“-”等運(yùn)算符添加或刪除事件處理方法。例如,以下語(yǔ)句是訂閱者s1.Listener(其中s1是Student類(lèi)對(duì)象)向事件源t(Teacher類(lèi)對(duì)象)訂閱ClassEvent事件,其中事件處理方法是Student類(lèi)的Listener方法:
t.ClassEvent+=newTeacher.delegateType(s1.Listener);4.創(chuàng)建引發(fā)事件的方法要通知訂閱了某個(gè)事件的所有對(duì)象,需要引發(fā)該事件,引發(fā)事件與調(diào)用方法相似,其語(yǔ)法格式如下:
事件名([參數(shù)表]);通常在事件源中包含引發(fā)事件的方法,例如,在Teacher類(lèi)中包含以下方法:publicvoidStart() //定義引發(fā)事件的方法{ Console.WriteLine(tname+"教師宣布開(kāi)始上課:"); if(ClassEvent!=null) ClassEvent(); //當(dāng)事件不空時(shí)引發(fā)該事件}5.確定引發(fā)該事件的時(shí)間在需要的時(shí)候調(diào)用引發(fā)事件的方法來(lái)觸發(fā)事件。例如,以下語(yǔ)句觸發(fā)事件:
t.Start();其中t為事件源對(duì)象,Start()為引發(fā)事件的方法。usingSystem;usingSystem.Collections;namespaceaaa{publicclassTeacher //教師類(lèi),事件源類(lèi){ privatestringtname; //教師姓名
publicdelegatevoiddelegateType(); //聲明委托類(lèi)型
publiceventdelegateTypeClassEvent;//聲明一個(gè)上課事件 publicTeacher(stringname) //構(gòu)造函數(shù) {this.tname=name;} publicvoidStart() //定義引發(fā)事件的方法 { Console.WriteLine(tname+"教師宣布開(kāi)始上課:"); if(ClassEvent!=null) ClassEvent(); //當(dāng)事件不空時(shí)引發(fā)該事件 } }學(xué)生上課示例:publicclassStudent //學(xué)生類(lèi),訂閱者類(lèi){ privatestringsname; //學(xué)生姓名 publicStudent(stringname)//構(gòu)造函數(shù) {this.sname=name;} publicvoidListener() //聽(tīng)課方法 { Console.WriteLine("學(xué)生"+sname+"正在認(rèn)真聽(tīng)課");} publicvoidRecord() //做筆記方法 {Console.WriteLine("學(xué)生"+sname+"正在做筆記");} publicvoidReading() //看書(shū)方法 {Console.WriteLine("學(xué)生"+sname+"正在認(rèn)真看書(shū)");} } classProgram {staticvoidMain(string[]args) { Teachert=newTeacher("李明"); Students1=newStudent("許強(qiáng)"); Students2=newStudent("陳兵"); Students3=newStudent("張英"); //以下是3個(gè)學(xué)生訂閱同一個(gè)事件
t.ClassEvent+=newTeacher.delegateType(s1.Listener); t.ClassEvent+=newTeacher.delegateType(s2.Reading); t.ClassEvent+=newTeacher.delegateType(s3.Record); t.Start(); //引發(fā)事件 }}}李明教師宣布開(kāi)始上課:許強(qiáng)正在認(rèn)真聽(tīng)課陳兵正在認(rèn)真看書(shū)張英正在做筆記該程序的執(zhí)行結(jié)果如下:【例6.11】設(shè)計(jì)一個(gè)控制臺(tái)應(yīng)用程序,說(shuō)明事件的使用。usingSystem;namespaceProj6_11{publicdelegatevoidmydelegate(intc,intn);//聲明一個(gè)事件委托類(lèi)型publicclassShape{ protectedintcolor;
publiceventmydelegateColorChange;//聲明一個(gè)事件 publicintpcolor//定義屬性 {set { intocolor=color;//保存原來(lái)的顏色 color=value;
ColorChange(ocolor,color);
//在color的值發(fā)生改變后,觸發(fā)事件。 } get { returncolor;} } publicShape()//構(gòu)造函數(shù) {color=0;}}classProgram{staticvoidMain(string[]argvs){Shapeobj=newShape();
obj.ColorChange+=newmydelegate(CCHandler);//訂閱事件 obj.pcolor=3;//改變顏色觸發(fā)事件 } staticvoidCCHandler(intc,intn)//事件處理方法 { Console.WriteLine("顏色從{0}改變?yōu)閧1}",c,n); }}}執(zhí)行結(jié)果:顏色從0改變?yōu)?6.12運(yùn)算符重載6.12.1運(yùn)算符重載概述運(yùn)算符重載是指同名運(yùn)算符可用于運(yùn)算不同類(lèi)型的數(shù)據(jù)。C#允許重載運(yùn)算符,以供自己的類(lèi)使用。其目的是讓使用類(lèi)對(duì)象像使用基本數(shù)據(jù)類(lèi)型一樣自然、合理。例如,設(shè)計(jì)一個(gè)名稱為MyAdd的類(lèi),其中對(duì)“+”運(yùn)算符進(jìn)行了重載,這樣對(duì)于該類(lèi)的兩個(gè)對(duì)象a和b,就可以進(jìn)行a+b的運(yùn)算。若要重載某個(gè)運(yùn)算符,需要編寫(xiě)一個(gè)函數(shù),其基本語(yǔ)法格式如下:publicstatic返回類(lèi)型operator運(yùn)算符(參數(shù)列表){
}所有運(yùn)算符重載均為類(lèi)的靜態(tài)方法。在C#中不是所有的運(yùn)算符都允許重載,以下是可重載的運(yùn)算符的完整
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 煤矸石綜合利用生產(chǎn)線項(xiàng)目節(jié)能評(píng)估報(bào)告
- 2025年注冊(cè)環(huán)保工程師模擬測(cè)試完美版帶解析
- 新質(zhì)智造產(chǎn)業(yè)園項(xiàng)目社會(huì)穩(wěn)定風(fēng)險(xiǎn)評(píng)估報(bào)告
- 2025年起重機(jī)司機(jī)(限門(mén)式起重機(jī))考試題模擬考試題庫(kù)及答案
- 2025年混凝土公司考試題及答案
- 高三試卷:甘肅、青海、寧夏金太陽(yáng)百校聯(lián)考2025屆高三11月聯(lián)考試題及答案地理答案
- 高三試卷:2025屆湖南a佳教育高三上學(xué)期11月聯(lián)考化學(xué)試卷
- 砸墻工程專(zhuān)業(yè)知識(shí)培訓(xùn)課件
- 給水工程防滲漏設(shè)計(jì)方案
- 生物制品相關(guān)知識(shí)培訓(xùn)課件
- 《文獻(xiàn)檢索課程》課件
- 低介電常數(shù)材料應(yīng)用
- 水平三(五年級(jí))體育《籃球:?jiǎn)问旨缟贤痘@》說(shuō)課稿課件
- 2023發(fā)電機(jī)自動(dòng)準(zhǔn)同期裝置整定計(jì)算技術(shù)導(dǎo)則
- GB/T 3672.1-2002橡膠制品的公差第1部分:尺寸公差
- 月度工作總結(jié)
- 箱涵高支模方案
- 第十章我國(guó)的環(huán)境保護(hù)政策和法規(guī)課件
- 綠化養(yǎng)護(hù)檢查記錄表
- 學(xué)生視力檔案表
- 《飼料學(xué)》粗飼料
評(píng)論
0/150
提交評(píng)論