版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第6章面向對象程序設計
6.1面向對象程序設計概述6.2命名空間6.3類6.4對象6.5構造函數(shù)和析構函數(shù)6.6靜態(tài)成員6.7屬性6.8方法6.9索引器6.10委托6.11事件6.12運算符重載6.13類的轉換6.1面向對象程序設計概述6.1.1面向對象的基本概念類和對象屬性、方法和事件封裝繼承重載與重寫6.1.2面向對象的優(yōu)點維護簡單。可擴充性。代碼重用。6.2命名空間6.2.1命名空間概述在.NET中,類是通過命名空間(namespace)來組織的。命名空間提供了可以將類分成邏輯組的方法,將系統(tǒng)中的大量類庫有序地組織起來,使得類更容易使用和管理。可以將命名空間想像成文件夾,類的文件夾就是命名空間,不同的命名空間內,可以定義許多類。在每個命名空間下,所有的類都是“獨立”且“唯一”的。6.2.2使用命名空間
在C#中,使用命名空間有兩種方式,一種是明確指出命名空間的位置,另一種是通過using關鍵字引用命名空間。直接定位在應用程序中,任何一個命名空間都可以在代碼中直接使用。例如:System.Console.WriteLine("ABC");這個語句是調用了System命名空間中Console類的WriteLine方法。1)使用using關鍵字在應用程序中要使用一個命名空間,還可以采取引用命名空間的方法,在引用后,應用程序中就可使用該命名空間內的任一個類了。引用命名空間的方法是利用using關鍵字,其使用格式如下:
using[別名=]命名空間或
using[別名=]命名空間.成員2)自定義命名空間在C#中,除了使用系統(tǒng)的命名空間外,還可以在應用程序中自已聲明命名空間。其使用語法格式如下:namespace命名空間名稱{命名空間定義體}其中,“命名空間名稱”指出命名空間的唯一名稱,必須是有效的C#標識符。例如,在應用程序中自定義Ns1命名空間:namespaceNs1{ classA{…} classB{…}}6.3類6.3.1類的聲明類的聲明語法格式如下:[類的修飾符]class類名[:基類名]{//類的成員;}[;]類的修飾符說明public公有類。表示不受限制對該類的訪問。protected保護類。表示只能從所在類和所在類派生的子類進行訪問。internal內部類。只有其所在類才能訪問。private私有類。只有該類才能訪問。abstract抽象類。表示該類是一個不完整的類,不允許建立類的實例。sealed密封類。不允許從該類派生新的類。例如,以下聲明了一個Person類:publicclassPerson{ publicintpno; //編號 publicstringpname; //姓名 publicvoidsetdata(intno,stringname) { pno=no;pname=name; } publicvoiddispdata() { Console.WriteLine("{0}{1}",pno,pname); }}6.3.2類的成員類的成員說明字段字段存儲類要滿足其設計所需要的數(shù)據(jù),亦稱為數(shù)據(jù)成員。屬性屬性是類中可以像類中的字段一樣被訪問的方法。屬性可以為類字段提供保護,避免字段在對象不知道的情況下被更改。方法方法定義類可以執(zhí)行的操作。方法可以接受提供輸入數(shù)據(jù)的參數(shù),并且可以通過參數(shù)返回輸出數(shù)據(jù)。方法還可以不使用參數(shù)而直接返回值。事件事件是向其他對象提供有關事件發(fā)生(如單擊按鈕或成功完成某個方法)通知的一種方式。索引器索引器允許以類似于數(shù)組的方式為對象建立索引。運算符運算符是對操作數(shù)執(zhí)行運算的術語或符號,如+、*、<等。構造函數(shù)構造函數(shù)是在第一次創(chuàng)建對象時調用的方法。它們通常用于初始化對象的數(shù)據(jù)。析構函數(shù)析構函數(shù)是當對象即將從內存中移除時由運行庫執(zhí)行引擎調用的方法。它們通常用來確保需要釋放的所有資源都得到了適當?shù)奶幚?。類成員的修飾符說明public公有成員。提供了類的外部界面,允許類的使用者從外部進行訪問,這是限制最少的一種訪問方式。private私有成員(默認的)。僅限于類中的成員可以訪問,從類的外部訪問私有成員是不合法的,如果在聲明中沒有出現(xiàn)成員的訪問修飾符,按照默認方式成員為私有的。protected保護成員。這類成員不允許外部訪問,但允許其派生類成員訪問。internal內部成員。允許同一個命名空間中的類訪問。readonly只讀成員。這類成員的值只能讀,不能寫。也就是說,除了賦予初始值外,在程序的任何部分將無法更改這個成員的值。6.3.3分部類分部類可以將類(結構或接口等)的聲明拆分到兩個或多個源文件中。若要拆分類的代碼,被拆分類的每一部分的定義前邊都要用partial關鍵字修飾。分部類的每一部分都可以存放在不同的文件中,編譯時會自動將所有部分組合起來構成一個完整的類聲明。6.4對象
6.4.1定義類的對象一旦聲明了一個類,就可以用它作為數(shù)據(jù)類型來定義類對象(簡稱為對象)。定義類的對象分以下兩步:1)定義對象引用其語法格式如下:類名對象名;例如,以下語句定義Person類的對象引用p:Personp;2)創(chuàng)建類的實例其語法格式如下:對象名=new類名();例如,以下語句創(chuàng)建Person類的對象實例:p=newPersone();以上兩步也可以合并成一步。其語法格式如下:類名對象名=new類名();例如:Personp=newPerson();理解對象引用和類實例的區(qū)別。兩個對象引用可以引用同一個對象,例如:Personp1=newPerson();Personp2=p1;p1p26.4.2訪問對象的字段訪問對象字段的語法格式如下:對象名.字段名其中,“.”是一個運算符,該運算符的功能是表示對象的成員。例如,前面定義的p對象的成員變量表示為:p.pno,p.pname6.4.3調用對象的方法調用對象的方法的語法格式如下:對象名.方法名(參數(shù)表)例如,調用前面定義的p對象的成員方法setdata為:p.setdata(101,"Mary");【例6.1】設計一個控制臺應用程序,說明調用對象方法的過程。usingSystem;namespaceProj6_1{publicclassTPoint//聲明類TPoint{intx,y;//類的私有字段publicvoidsetpoint(intx1,inty1){ x=x1;y=y1;}publicvoiddispoint(){Console.WriteLine("({0},{1})",x,y);}}classProgram{staticvoidMain(string[]args){TPointp1=newTPoint(); //定義對象p1 p1.setpoint(2,6); Console.Write("第一個點=>"); p1.dispoint(); TPointp2=newTPoint(); //定義對象p2 p2.setpoint(8,3); Console.Write("第二個點=>"); p2.dispoint();}}}6.5構造函數(shù)和析構函數(shù)6.5.1構造函數(shù)1.什么是構造函數(shù)構造函數(shù)是在創(chuàng)建給定類型的對象時執(zhí)行的類方法。構造函數(shù)具有如下性質:構造函數(shù)的名稱與類的名稱相同。構造函數(shù)盡管是一個函數(shù),但沒有任何類型,即它既不屬于返回值函數(shù)也不屬于void函數(shù)。一個類可以有多個構造函數(shù),但所有構造函數(shù)的名稱都必須相同,它們的參數(shù)各不相同,即構造函數(shù)可以重載。當類對象創(chuàng)建時,構造函數(shù)會自動地執(zhí)行;由于它們沒有返回類型,因此不能像其他函數(shù)那樣進行調用。當類對象聲明時,調用哪一個構造函數(shù)取決于傳遞給它的參數(shù)類型。構造函數(shù)不能被繼承。2.調用構造函數(shù)當定義類對象時,構造函數(shù)會自動執(zhí)行。1)調用默認構造函數(shù)不帶參數(shù)的構造函數(shù)稱為默認構造函數(shù)。無論何時,只要使用new運算符實例化對象,并且不為new提供任何參數(shù),就會調用默認構造函數(shù)。假設一個類包含有默認構造函數(shù),調用默認構造函數(shù)的語法如下:類名對象名=new類名();如果沒有為對象提供構造函數(shù),則默認情況下C#將創(chuàng)建一個構造函數(shù),該構造函數(shù)實例化對象,并將所有成員變量設置為相應的默認值。2)調用帶參數(shù)的構造函數(shù)假設一個類中包含有帶參數(shù)的構造函數(shù),調用這種帶參數(shù)的構造函數(shù)的語法如下:類名對象名=new類名(參數(shù)表);【例6.2】設計一個控制臺應用程序,說明調用構造函數(shù)的過程。namespaceProj6_2{classProgram{publicclassTPoint1 //聲明類TPoint1{ intx,y; //類的私有變量 publicTPoint1(){} //默認的構造函數(shù) publicTPoint1(intx1,inty1) //帶參數(shù)的構造函數(shù) {x=x1;y=y1;} publicvoiddispoint() {Console.WriteLine("({0},{1})",x,y);} } staticvoidMain(string[]args) {TPoint1p1=newTPoint1(); //調用默認的構造函數(shù) Console.Write("第一個點=>"); p1.dispoint(); TPoint1p2=newTPoint1(8,3);//調用帶參數(shù)的構造函數(shù) Console.Write("第二個點=>"); p2.dispoint(); }}}6.5.2析構函數(shù)1.什么是析構函數(shù)在對象不再需要時,希望確保它所占的存儲空間能被收回。C#中提供了析構函數(shù)用于專門釋放被占用的系統(tǒng)資源。析構函數(shù)具有如下性質:析構函數(shù)在類對象銷毀時自動執(zhí)行。一個類只能有一個析構函數(shù),而且析構函數(shù)沒有參數(shù),即析構函數(shù)不能重載。析構函數(shù)的名稱是“~”加上類的名稱(中間沒有空格)。與構造函數(shù)一樣,析構函數(shù)也沒有返回類型。析構函數(shù)不能被繼承。2.調用析構函數(shù)當一個對象被系統(tǒng)銷毀時自動調用類的析構函數(shù)?!纠?.3】設計一個控制臺應用程序,說明調用析構函數(shù)的過程。usingSystem;namespaceProj6_3{classProgram{publicclassTPoint2//聲明類TPoint2{ intx,y; publicTPoint2(intx1,inty1) //帶參數(shù)的構造函數(shù) {x=x1;y=y1;} ~TPoint2() {Console.WriteLine("點=>({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)字段是類中所有對象共享的成員,而不是某個對象的成員,也就是說靜態(tài)字段的存儲空間不是放在每個對象中,而是和方法一樣放在類公共區(qū)中。對靜態(tài)字段的操作和一般字段一樣,定義為私有的靜態(tài)字段不能被外界訪問。靜態(tài)字段的使用方法如下:(1)靜態(tài)字段的定義與一般字段相似,但前面要加上static關鍵詞。(2)在訪問靜態(tài)字段時采用如下格式:類名.靜態(tài)字段名6.6.2靜態(tài)方法靜態(tài)方法與靜態(tài)字段類似,也是從屬于類,都是類的靜態(tài)成員。只要類存在,靜態(tài)方法就可以使用,靜態(tài)方法的定義是在一般方法定義前加上static關鍵字。調用靜態(tài)方法的格式如下:類名.靜態(tài)方法名(參數(shù)表);注意:靜態(tài)方法只能訪問靜態(tài)字段、其他靜態(tài)方法和類以外的函數(shù)及數(shù)據(jù),不能訪問類中的非靜態(tài)成員(因為非靜態(tài)成員只有對象存在時才有意義)。但靜態(tài)字段和靜態(tài)方法可由任意訪問權限許可的成員訪問。6.7屬性6.7.1什么是屬性屬性描述了對象的具體特性,它提供了對類或對象成員的訪問。C#中的屬性更充分地體現(xiàn)了對象的封裝性,屬性不直接操作類的字段,而是通過訪問器進行訪問。6.7.2屬性聲明屬性在類模塊里是采用下面的方式進行聲明的,即指定變量的訪問級別、屬性的類型、屬性的名稱,然后是get訪問器或者set訪問器代碼塊。其語法格式如下:修飾符數(shù)據(jù)類型屬性名稱{get訪問器set訪問器}其中,修飾符有new、public、protected、internal、private、static、virtual、override和abstract?!纠?.7】設計一個控制臺應用程序,說明屬性的使用。usingSystem;namespaceProj6_7{publicclassTPoint3 //聲明類TPoint3{intx,y;publicintpx{ get //get訪問器 {returnx;} set //set訪問器 {x=value;}}publicintpy{ get //get訪問器 {returny;} set //set訪問器 {y=value;}}};classProgram{staticvoidMain(string[]args){ TPoint3p=newTPoint3(); p.px=3;p.py=8;//屬性寫操作 Console.WriteLine("點=>({0},{1})",p.px,p.py);//屬性讀操作}}}點=>(3,8)6.8方法
6.8.1什么是方法方法包含一系列的代碼塊。從本質上來講,方法就是和類相關聯(lián)的動作,是類的外部界面。用戶可以通過外部界面來操作類的私有字段。6.8.2方法的定義定義方法的基本格式如下:修飾符返回類型方法名(參數(shù)列表){ //方法的具體實現(xiàn);}6.8.3方法的返回值方法可以向調用方返回某一個特定的值。如果返回類型不是void,則該方法可以用return關鍵字來返回值,return還可以用來停止方法的執(zhí)行。例如,以下類MyClass3中的addnum方法用return關鍵字來返回值:publicclassMyClass3{ intnum=0; publicintaddnum(intnum1) {returnnum+num1; }}6.8.4方法的參數(shù)方法中的參數(shù)是保證不同的方法間互動的重要橋梁,方便用戶對數(shù)據(jù)的操作。C#中方法的參數(shù)有4種類型。1.值參數(shù)不含任何修飾符,當利用值向方法傳遞參數(shù)時,編譯程序給實參的值做一份拷貝,并且將此拷貝傳遞給該方法,被調用的方法不會修改內存中實參的值,所以使用值參數(shù)時可以保證實際值的安全性。在調用方法時,如果形參的類型是值參數(shù)的話,調用的實參的表達式必須保證是正確的值表達式。例如,前面MyClass3類中addnum方法中的參數(shù)就是值參數(shù)。2.引用型參數(shù)
以ref修飾符聲明的參數(shù)屬引用型參數(shù)。引用型參數(shù)本身并不創(chuàng)建新的存儲空間,而是將實參的存儲地址傳遞給形參,所以對形參的修改會影響原來實參的值。在調用方法前,引用型實參必須被初始化,同時在調用方法時,對應引用型參數(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ù)類似,輸出型參數(shù)也不開辟新的內存區(qū)域。它與引用型參數(shù)的差別在于,調用方法前無需對變量進行初始化。輸出型參數(shù)用于傳遞方法返回的數(shù)據(jù),out修飾符后應跟隨與形參的類型相同的類型,用來聲明在方法返回后傳遞的變量經過了初始化。例如: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關鍵字可以指定在參數(shù)數(shù)目可變處采用參數(shù)的方法參數(shù)。在方法聲明中的params關鍵字之后不允許任何其他參數(shù),并且在方法聲明中只允許一個params關鍵字。有數(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方法的重載
方法的重載是指調用同一方法名,但是使用不同的數(shù)據(jù)類型參數(shù)或者次序不一致的參數(shù)。只要一個類中有兩個以上的同名方法,且使用的參數(shù)類型或者個數(shù)不同,編譯器就可以判斷在哪種情況下調用哪種方法了。為此,C#中引入了成員簽名的概念。成員簽名包含成員的名稱和參數(shù)列表,每個成員簽名在類型中必須是唯一的,只要成員的參數(shù)列表不同,成員的名稱可以相同。如果同一個類有兩個或多個這樣的成員(方法、屬性、構造函數(shù)等),它們具有相同的名稱和不同的參數(shù)列表,則稱該同類成員進行了重載,但它們的成員簽名是不同的。例如,下面的代碼實現(xiàn)了MethodTest方法的重載(假設都是某個類的成員),它們是不同的成員簽名:
publicintMethodTest(inti,intj) //重載方法1{ //代碼}publicintMethodTest(inti) //重載方法2{ //代碼}publicstringMethodTest(stringsr) //重載方法3{ //代碼}6.9索引器6.9.1什么是索引器索引器提供了一種訪問類或結構的方法,即允許按照與數(shù)組相同的方式對類、結構或接口進行索引。它的引入是為了使程序更加直觀、易于理解。例如,可以有一個大學名稱類University,其中有一個name數(shù)組字段可能包含一些大學名稱,un是該類的一個對象,類中索引器允許訪問這些大學名稱,例如:un[0]="清華大學";un[1]="北京大學";un[3]="武漢大學";6.9.2定義索引器要聲明類或結構上的索引器,需使用this關鍵字,其語法格式如下:
publicintthis[intindex]//索引器聲明{//get和set訪問器}其中,this關鍵字引用類的當前實例。從中看到,索引器像對普通屬性一樣,為它提供get和set方法,這些訪問器指定當使用該索引器時將引用到什么內部成員。例如,帶有索引器的University類設計如下: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和其他語言支持函數(shù)指針的概念,允許在運行時選擇要調用的函數(shù)。Java不提供任何具有函數(shù)指針功能的結構,但C#提供這種構造。通過使用Delegate類,委托實例可以封裝屬于可調用實體的方法。委托具有以下特點:委托類似于C++函數(shù)指針,但它是類型安全的。委托允許將方法作為參數(shù)進行傳遞。委托可用于定義回調方法。委托可以鏈接在一起。例如,可以對一個事件調用多個方法。方法不需要與委托簽名精確匹配。委托相當于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); /*通過pf調用函數(shù)f1*/
printf("%d,%d,%d\n",a,b,c);
pf=f2; /*讓pf指向函數(shù)f2*/
(*pf)(a,b,c); /*通過pf調用函數(shù)f2*/
printf("%d,%d,%d\n",a,b,c);}一個C/C++函數(shù)指針的示例6.10.2定義和使用委托定義和使用委托有3個步驟,即聲明、實例化和調用。1.聲明委托類型聲明委托類型就是告訴編譯器這種類型代表了哪種類型的方法。使用以下語法聲明委托類型:[修飾符]delegate返回類型委托類型名(參數(shù)列表);在聲明一個委托類型時,每個委托類型都描述參數(shù)的數(shù)目和類型,以及它可以引用的方法的返回類型。每當需要一組新的參數(shù)類型或新的返回類型時,都必須聲明一個新的委托類型。例如:privatedelegatevoidmydelegate(intn);上述代碼聲明了一個委托mydelegate,該委托類型可以引用一個采用int作為參數(shù)并返回void的方法。2.實例化委托聲明了委托類型后,必須創(chuàng)建一個它的實例,即創(chuàng)建委托對象并使之與特定方法關聯(lián)。定義委托對象的語法格式如下:委托類型名委托對象名;例如,以下語句創(chuàng)建了mydelegate委托的一個委托對象p:mydelegatep;沒有實例化另外,委托對象還需實例化為調用的方法,通常將這些方法放在一個類中(也可以將這些方法放在程序的Program類中),假設一個MyDeClass類如下:classMyDeClass{ publicvoidfun1(intn) { Console.WriteLine("{0}的2倍={1}",n,2*n); } publicvoidfun2(intn) { Console.WriteLine("{0}的3倍={1}",n,3*n); }}包含委托所指向方法的類可以通過以下語句實例化委托對象p:MyDeClassobj=newMyDeClass();mydelegatep=newmydelegate(obj.fun1);其中,MyDeClass類中的fun1方法有一個int形參,其返回類型為void,它必須與mydelegate類型的聲明相一致。定義并實例化委托對象3.調用委托創(chuàng)建委托對象后,通常將委托對象傳遞給將調用該委托的其他代碼。通過委托對象的名稱(后面跟著要傳遞給委托的參數(shù),放在括號內)調用委托對象。其使用語法格式如下:委托對象名(實參列表);例如,以下語句調用委托p:p(100);委托對象是不可變的,即設置與它們匹配的簽名后就不能再更改簽名了。但是,如果其他方法具有同一簽名,也可以指向該方法。例如:MyDeClassobj=newMyDeClass();mydelegatep=newmydelegate(obj.fun1);p(5);p=newmydelegate(obj.fun2);p(3);【例6.9】設計一個控制臺應用程序,說明委托的使用。usingSystem;namespaceProj6_9{delegatedoublemydelegate(doublex,doubley);//聲明委托類型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作為引用類型,也可以改為值類型,等價的主函數(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));}可以直接把方法名賦值給委托對象來創(chuàng)建一個委托實例6.10.3委托對象封裝多個方法委托對象可以封裝多個方法,這些方法的集合稱為調用列表。委托使用“+”、“-”、“+=”和“-=”等運算符向調用列表中增加或移除事件處理方法?!纠?.10】設計一個控制臺應用程序,說明委托對象封裝多個方法的使用。usingSystem;namespaceProj6_10{delegatevoidmydelegate(doublex,doubley);//聲明委托類型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方法添加到調用列表中 a=obj.sub; p+=a;//將sub方法添加到調用列表中 a=obj.mul; p+=a;//將mul方法添加到調用列表中 a=obj.div; p+=a;//將div方法添加到調用列表中 p(5,8); }}}6.10.4使委托與匿名方法關聯(lián)所謂匿名方法就是沒有方法名稱的方法。當將委托與匿名方法關聯(lián)時,直接給出方法的函數(shù)體,其一般語法格式如下:delegate返回類型委托類型名(參數(shù)列表);委托類型名委托對象名=返回類型(參數(shù)列表){/*匿名方法代碼*/};托對象名(實參列表)第1個語句聲明委托類型;第2個語句定義匿名方法并將其與委托對象關聯(lián);第3個語句調用委托。例如,以下程序段就是使委托與匿名方法關聯(lián),并調用該委托:delegatevoidmydelegate(stringmystr);//聲明委托類型classProgram{staticvoidMain(string[]args){mydelegatep=delegate(stringmystr){Console.WriteLine(mystr);};p("String");//輸出:String}}6.11事件6.11.1什么是事件事件是類在發(fā)生其關注的事情時用來提供通知的一種方式。例如,封裝用戶界面控件的類可以定義一個在用戶單擊時候發(fā)生的一個事件??丶惒魂P心單擊按鈕時候發(fā)生了什么,但是它需要告知派生類單擊事件已經發(fā)生,然后,派生類可以選擇如何響應。命令按鈕用戶單擊引發(fā)執(zhí)行Click事件過程
以課堂講課為例,某教室里有若干學生,當上課教師宣布“開始上課”時,本教室里的學生聽到后做各種上課準備,有的認真聽課,有的認真看書,有的做筆記,而不在本教室的學生則不會。教師開始上課學生做某種動作事件關聯(lián)教師類學生類
從程序的角度看,當教師宣布“開始上課”時就是發(fā)生了一個事件,是該教師通知該事件發(fā)生,所以該教師是事件源,本教室的學生(稱為訂閱者)接到通知后開始做上課準備(事件的訂閱者對事件的處理)。6.11.2事件的創(chuàng)建和使用下面介紹在C#中創(chuàng)建和使用事件的步驟。1.為事件創(chuàng)建一個委托類型和聲明事件
在事件源類中聲明一個事件委托類型,該委托類型的返回值類型通常為void。其一般的語法格式如下:
delegatevoid委托類型名([觸發(fā)事件的對象名,事件參數(shù)]);例如在課堂講課例子中,設計事件源類為教師類Teacher,其中通過以下語句聲明一個委托類型delegateType,其委托的事件處理方法返回類型為void,不帶任何參數(shù):
publicdelegatevoiddelegateType(); //聲明委托類型事件是事件源類的成員。在事件源類中以關鍵字event聲明一個事件,其一般語法格式如下:
[修飾符]event委托類型名事件名;其中,“修飾符”指出類的用戶訪問事件的方式,可以為public、private、protected、internal、protectedinternal、static或virtual等。例如,在Teacher類包含以下語句聲明一個上課事件:publiceventdelegateTypeClassEvent; //聲明一個上課事件2.創(chuàng)建事件處理的方法
當事件觸發(fā)時需要調用事件處理方法,需設計相應的事件處理方法。既可以將事件處理方法放在訂閱者類中,也可以將將事件處理方法放在單獨的類中。例如在課堂講課例子中,設計訂閱者類為學生類Student,在該類中設計以下3個事件處理方法:publicvoidListener() //聽課方法{Console.WriteLine("學生"+sname+"正在認真聽課");}publicvoidRecord() //做筆記方法{Console.WriteLine("學生"+sname+"正在做筆記");}publicvoidReading() //看書方法{Console.WriteLine("學生"+sname+"正在認真看書");}3.訂閱事件
向事件源類的事件中添加事件處理方法中的一個委托,這個過程稱為訂閱事件,這個過程通常是在主程序中進行的,首先必須定義一個包含事件的類的對象,然后將事件處理方法和該對象關聯(lián)起來,其格式如下:
事件類對象名.事件名+=new委托類型名(事件處理方法);其中,還可以使用“-=”、“+”、“-”等運算符添加或刪除事件處理方法。例如,以下語句是訂閱者s1.Listener(其中s1是Student類對象)向事件源t(Teacher類對象)訂閱ClassEvent事件,其中事件處理方法是Student類的Listener方法:
t.ClassEvent+=newTeacher.delegateType(s1.Listener);4.創(chuàng)建引發(fā)事件的方法要通知訂閱了某個事件的所有對象,需要引發(fā)該事件,引發(fā)事件與調用方法相似,其語法格式如下:
事件名([參數(shù)表]);通常在事件源中包含引發(fā)事件的方法,例如,在Teacher類中包含以下方法:publicvoidStart() //定義引發(fā)事件的方法{ Console.WriteLine(tname+"教師宣布開始上課:"); if(ClassEvent!=null) ClassEvent(); //當事件不空時引發(fā)該事件}5.確定引發(fā)該事件的時間在需要的時候調用引發(fā)事件的方法來觸發(fā)事件。例如,以下語句觸發(fā)事件:
t.Start();其中t為事件源對象,Start()為引發(fā)事件的方法。usingSystem;usingSystem.Collections;namespaceaaa{publicclassTeacher //教師類,事件源類{ privatestringtname; //教師姓名
publicdelegatevoiddelegateType(); //聲明委托類型
publiceventdelegateTypeClassEvent;//聲明一個上課事件 publicTeacher(stringname) //構造函數(shù) {this.tname=name;} publicvoidStart() //定義引發(fā)事件的方法 { Console.WriteLine(tname+"教師宣布開始上課:"); if(ClassEvent!=null) ClassEvent(); //當事件不空時引發(fā)該事件 } }學生上課示例:publicclassStudent //學生類,訂閱者類{ privatestringsname; //學生姓名 publicStudent(stringname)//構造函數(shù) {this.sname=name;} publicvoidListener() //聽課方法 { Console.WriteLine("學生"+sname+"正在認真聽課");} publicvoidRecord() //做筆記方法 {Console.WriteLine("學生"+sname+"正在做筆記");} publicvoidReading() //看書方法 {Console.WriteLine("學生"+sname+"正在認真看書");} } classProgram {staticvoidMain(string[]args) { Teachert=newTeacher("李明"); Students1=newStudent("許強"); Students2=newStudent("陳兵"); Students3=newStudent("張英"); //以下是3個學生訂閱同一個事件
t.ClassEvent+=newTeacher.delegateType(s1.Listener); t.ClassEvent+=newTeacher.delegateType(s2.Reading); t.ClassEvent+=newTeacher.delegateType(s3.Record); t.Start(); //引發(fā)事件 }}}李明教師宣布開始上課:許強正在認真聽課陳兵正在認真看書張英正在做筆記該程序的執(zhí)行結果如下:【例6.11】設計一個控制臺應用程序,說明事件的使用。usingSystem;namespaceProj6_11{publicdelegatevoidmydelegate(intc,intn);//聲明一個事件委托類型publicclassShape{ protectedintcolor;
publiceventmydelegateColorChange;//聲明一個事件 publicintpcolor//定義屬性 {set { intocolor=color;//保存原來的顏色 color=value;
ColorChange(ocolor,color);
//在color的值發(fā)生改變后,觸發(fā)事件。 } get { returncolor;} } publicShape()//構造函數(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í)行結果:顏色從0改變?yōu)?6.12運算符重載6.12.1運算符重載概述運算符重載是指同名運算符可用于運算不同類型的數(shù)據(jù)。C#允許重載運算符,以供自己的類使用。其目的是讓使用類對象像使用基本數(shù)據(jù)類型一樣自然、合理。例如,設計一個名稱為MyAdd的類,其中對“+”運算符進行了重載,這樣對于該類的兩個對象a和b,就可以進行a+b的運算。若要重載某個運算符,需要編寫一個函數(shù),其基本語法格式如下:publicstatic返回類型operator運算符(參數(shù)列表){
}所有運算符重載均為類的靜態(tài)方法。在C#中不是所有的運算符都允許重載,以下是可重載的運算符的完整
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 人教部編版六年級語文上冊第25課《少年閏土》精美課件
- 2024年度智能校園班班通系統(tǒng)集成合同
- 2024年黑龍江客運資格證技巧
- 2024年昆明客運駕駛員技能測試題
- 人教部編版六年級語文上冊《語文園地七》精美課件
- 2024年黑龍江客運從業(yè)資格證需要什么材料
- 2024年建筑工程施工標準合同范例
- 社區(qū)開展幼兒園安全自查報告總結
- 《第19課 戰(zhàn)后資本主義的新變化》(同步訓練)高中歷史必修2-人教版-2024-2025學年
- 架空線路安裝施工方案
- 國家開放大學《監(jiān)督學》形考任務(1-4)試題解析和答案
- 不斷把人民對美好生活的向往變?yōu)楝F(xiàn)實PPT實現(xiàn)人民對美好生活向往的路徑PPT課件(帶內容)
- DB43T 2428-2022 水利工程管理與保護范圍劃定技術規(guī)范
- GB/T 39968-2021建筑用通風百葉窗技術要求
- GB/T 1771-2007色漆和清漆耐中性鹽霧性能的測定
- 內科醫(yī)保入院指征
- 美濟礁 仁愛礁
- 茶文化與茶健康教學課件
- 問診及體格檢查課件
- 屯蘭瓦斯爆炸原因分析
- 員工心理健康工作講座課件
評論
0/150
提交評論