C#教程-最佳的入門教程_第1頁
C#教程-最佳的入門教程_第2頁
C#教程-最佳的入門教程_第3頁
C#教程-最佳的入門教程_第4頁
C#教程-最佳的入門教程_第5頁
已閱讀5頁,還剩20頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

C#語言第一部分面向?qū)ο螅ㄒ唬╊惡蚆ain方法usingSystem; namespaceEdu.Study.OO.MainMethod{classProgram{ staticvoidMain(string[]args){ Console.WriteLine("HelloWorld"); }}}C#語言第一部分面向?qū)ο螅ǘ╊愵愂敲嫦驅(qū)ο蟮幕A(chǔ),類表現(xiàn)出的最基本特性是其“封裝性”。類是某一些具有相同屬性和行為對象的抽象。例如:波斯貓、野貓、家貓、花貓都具有相同的屬性和行為,所以被抽象成為貓類。類具有屬性和方法,表示這個(gè)類所代表的對象具有的特性和行為。從類實(shí)例化對象后,對象就可以給類中定義的屬性“賦值”或運(yùn)行類中定義的方法,屬性和方法和每個(gè)對象相關(guān),即相同類的不同的對象具有相同的屬性,但屬性的屬性值可以不同;具有相同的方法,但方法運(yùn)行的結(jié)果可以不同。類需要將和其相關(guān)的屬性和方法“封裝”起來,并和對象進(jìn)行綁定??聪旅娴睦樱孕欣斫猓簎singSystem;namespaceEdi.Study.OO.Class{publicclassPerson{privatestringname;privateintage;privateboolsex;/*屬性定義,在面向?qū)ο缶幊汤铮侄巫鳛楸4鎸傩灾档淖兞?,而屬性則需要使用特殊的行來表現(xiàn)。一般來說一對get/set行為用來展現(xiàn)對象的屬性,其中g(shù)et用于2獲取該對象的屬性;set用于設(shè)置該對象的屬性get/set稱為屬性的訪問器*///姓名屬性publicstringName{get{//get訪問器必須返回一個(gè)值,作為該屬性的“屬性值return;//.運(yùn)算符的作用是訪問某個(gè)對象的屬性或方法//this關(guān)鍵字表示“當(dāng)前實(shí)例”,即哪一個(gè)對象正在操作屬性訪問器,this就表示哪個(gè)對象//所以一般說法,this表示“當(dāng)前對象”,使用this.訪問的是“聲明在本類中”的屬性和方法}set{//set訪問器具有一個(gè)局部變量value,該值是從外部設(shè)置給該屬性的值=value;}//屬性的基本要求:get訪問器必須返回一個(gè)值,該值類型和屬性類型相同;set訪問器可以設(shè)置一個(gè)值,這個(gè)值保存在什么地方倒無所謂}//年齡屬性publicintAge{get{returnage;}set{age=value;}}//性別屬性publicboolSex{get{returnsex;}set{sex=value;}}//顯示個(gè)人信的方法publicvoidShowMe(){//使用this.Name,此時(shí)屬性Name的get訪問器會(huì)運(yùn)行,返回Name屬性的屬性值,其它屬性同理Console.WriteLine("姓名:{0},性別:{1},年齡:{2}歲。",this.Name,this.Sex,this.Age);}/*字段、屬性和方法前面,都可以使用public,protected,private和internal這四種訪問修飾符來修飾;public表示字段、屬性或方法為“公開”,公開的成員不僅可以被類中的其它成員訪問到,也可以通過這個(gè)類的對象訪問到;private表示字段、屬性或方法為“私有”,私有的成員只能被類中的其它成員訪問到,無法通過類的對象訪問到;protected和internal稍候介紹;*/}classProgram{staticvoidMain(string[]args){//通過new運(yùn)算符可以實(shí)例化一個(gè)對象//實(shí)例化Person類的對象,保存在person變量中Personp1=newPerson();Personp2=newPerson();//設(shè)置person對象的各個(gè)屬性,使用person.Name="王寶寶",Name屬性的set訪問器會(huì)被運(yùn)行,等號(hào)右邊的值"王寶寶"傳遞給set訪問器的value變量p1.Name="王寶寶";p1.Age=21;p1.Sex=false;p2.Name="李大大";p2.Age=18;p2.Sex=true;//使用”.”操作符訪問person對象的ShowMe方法,顯示結(jié)果p1.ShowMe();p2.ShowMe();}}}C#語言第一部分面向?qū)ο螅ㄈο蟮臉?gòu)造上一章我們介紹了一個(gè)Person類,它可以正常工作,但從邏輯上存在很多問題。首先我們注意到,Person類對象實(shí)例化完畢后,我們才去確定其屬性,如Name,Sex,Age屬性。但客觀情況下,這些屬性應(yīng)該是同對象生成一起賦值的。一句話,當(dāng)對象被實(shí)例化的同時(shí),對象的屬性就應(yīng)當(dāng)有初始值,反映到代碼中,就是“用來保存屬性值的字段應(yīng)該有初始值”構(gòu)造器,也成為構(gòu)造方法,構(gòu)造函數(shù),就是專門用來做這件事情的。一個(gè)類可以有0或多個(gè)構(gòu)造器,在有多個(gè)構(gòu)造器的情況里,各個(gè)構(gòu)造器的參數(shù)必須不同。在C#類中,有這樣一類特殊的方法,沒有返回值類型,方法名必須和類名相同,可以有參數(shù)列表。這類方法就叫做構(gòu)造器,構(gòu)造器通過new操作符指定,在實(shí)例化對象的同時(shí)運(yùn)行。我們用構(gòu)造器來改造上一章講到的Person類。usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespace{//人類,這次我們修改一下Person類//在Person類生成對象的同時(shí),Name屬性,Sex屬性和Age屬性的值就應(yīng)該確定,而不應(yīng)該在生成對象后再進(jìn)行設(shè)置,這是不符合客觀規(guī)律的。//在對象實(shí)例化的同時(shí)對屬性進(jìn)行設(shè)置,就要用到構(gòu)造器publicclassPerson{privatestringname;privateintage;privateboolsex;//人類,這次我們修改一下Person類//在Person類生成對象的同時(shí),Name屬性,Sex屬性和Age屬性的值就應(yīng)該確定,而不應(yīng)該在生成對象后再進(jìn)行設(shè)置,這是不符合客觀規(guī)律的。//在對象實(shí)例化的同時(shí)對屬性進(jìn)行設(shè)置,就要用到“構(gòu)造器”publicPerson(){="小王";this.age=22;this.sex=true;}//帶有參數(shù)的構(gòu)造器publicPerson(stringname,intage,boolsex){this.Name=name;this.Age=age;this.sex=sex;//這里,Sex屬性}//帶有部分參數(shù)的構(gòu)造器publicPerson(intage,boolsex){this.Name="小?王a?";this.Age=age;this.sex=sex;//這里,Sex屬性}//帶有部分參數(shù)的構(gòu)造器publicPerson(boolsex){this.Name="小?王a?";this.Age=22;this.sex=sex;//這里,Sex屬性}publicstringName{get{//get訪問器必須返回一個(gè)值,作為該屬性的“屬性值return;}set{//set訪問器具有一個(gè)局部變量value,該值是從外部設(shè)置給該屬性的值=value;}}publicintAge{get{returnage;}set{age=value;}}//性別屬性,這次我們?nèi)サ袅薙ex的set訪問器。//由于通過構(gòu)造器已經(jīng)設(shè)置了Sex屬性,所以無需通過set訪問器來設(shè)置該屬性//按照一般情況,Sex屬性在對象實(shí)例化后,不應(yīng)該設(shè)置該屬性。//屬性可以只具有set訪問器或get訪問器,即“只讀”或“只寫”的屬性publicboolSex{get{returnsex;}}//顯示個(gè)人信息的方法publicvoidShowMe(){Console.WriteLine("姓名:{0},性別:{1},年齡:{2}歲。",this.Name,this.Sex,this.Age);}}classProgram{staticvoidMain(string[]args){//刪除掉publicPerson()構(gòu)造器,查看程序編譯情況//刪除掉所有的構(gòu)造器,查看程序編譯情況Personperson=newPerson();person.ShowMe();//person.Sex=true;//只讀屬性禁止了給屬性設(shè)置值person=newPerson(false);person.ShowMe();person=newPerson(18,true);person.ShowMe();person=newPerson("小麗",23,false);person.ShowMe();}}}

我們給Person類增加了若干個(gè)“構(gòu)造器”,并修改Sex屬性為只讀,從而讓Person類更更符合客觀實(shí)際。對于任何一個(gè)類,可以不人為提供構(gòu)造器,此時(shí)編譯器會(huì)賦予類一個(gè)“默認(rèn)構(gòu)造器”,即沒有參數(shù)的構(gòu)造器。這個(gè)構(gòu)造器什么也不做,僅僅是為了new操作符能夠得以指定一個(gè)構(gòu)造器。而我們一旦定義了有參數(shù)的構(gòu)造器,編譯器便會(huì)這樣認(rèn)為“這個(gè)類的對象必須提供參數(shù)才能夠?qū)嵗保悴辉贂?huì)提供無參數(shù)的默認(rèn)構(gòu)造器了。所以一個(gè)類如果同時(shí)需要有默認(rèn)構(gòu)造器和有參數(shù)的構(gòu)造器,則默認(rèn)構(gòu)造器必須手動(dòng)提供,不要指望編譯器會(huì)自動(dòng)生成。現(xiàn)在我們可以完整定義new操作符的語法規(guī)范:類名變量名=new類構(gòu)造器名(構(gòu)造器實(shí)參數(shù)列表);C#語言第一部分面向?qū)ο螅ㄋ模┳侄文J(rèn)值C#中,可以給類字段以一個(gè)默認(rèn)值,這樣一方面可以簡化構(gòu)造器的代碼,另一方面較為直觀,是一種推薦的方式。這一章比較簡單,可結(jié)合上一章深入理解構(gòu)造器的作用??创a:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespace{//還是那個(gè)人類。//通過構(gòu)造器publicclassPerson{//保存名字的字段,默認(rèn)值為小王privatestringname="小王";//保存年齡的字段,默認(rèn)值為0privateintage=22;//保存性別的字段,true為男性,false為女性,默認(rèn)值為女性privateboolsex=false;//默認(rèn)構(gòu)造器,由于字段定義了默認(rèn)值,所以構(gòu)造器中無需給字段賦值publicPerson(){}//帶有參數(shù)的構(gòu)造器,這里的構(gòu)造器給所有字段都賦了值,所以無視默認(rèn)值publicPerson(stringname,intage,boolsex){this.Name=name;this.Age=age;this.sex=sex;}//帶有部分參數(shù)的構(gòu)造器,這里只給sex和age字段賦值,而name字段本身就有默認(rèn)值publicPerson(intage,boolsex){this.Age=age;this.sex=sex;//這里,Sex屬性}//帶有部分參數(shù)的構(gòu)造器,這里只給sex字段賦值,其它字段都有默認(rèn)值publicPerson(boolsex){this.sex=sex;}publicstringName{get{//get訪問器必須返回一個(gè)值,作為該屬性的“屬性值return;}set{//set訪問器具有一個(gè)局部變量value,該值是從外部設(shè)置給該屬性的值=value;}}publicintAge{get{returnage;}set{age=value;}}publicboolSex{get{returnsex;}}//顯示個(gè)人信息的方法publicvoidShowMe(){Console.WriteLine("姓名:{0},性別:{1},年齡:{2}歲o。",this.Name,this.Sex,this.Age);}}classProgram{staticvoidMain(string[]args){//刪除掉publicPerson()構(gòu)造器,查看程序編譯情況//刪除掉所有的構(gòu)造器,查看程序編譯情況Personperson=newPerson();person.ShowMe();//person.Sex=true;//只讀屬性禁止了給屬性設(shè)置值person=newPerson(false);person.ShowMe();person=newPerson(18,true);person.ShowMe();person=newPerson("小?麗¤?",23,false);person.ShowMe();}}}在聲明字段的同時(shí),可以用賦值運(yùn)算符(=)在字段后面直接加上一個(gè)值(例如第17行),但這和給變量賦值是兩個(gè)概念。以賦值運(yùn)算符跟隨在字段之后的值稱為字段的“默認(rèn)值”。這只是一種形式,并不是寫在這里就在這里發(fā)生賦值,真正發(fā)生賦值的時(shí)機(jī)還是在構(gòu)造器中,只不過……無論我們通過哪個(gè)構(gòu)造器創(chuàng)建類的對象實(shí)例,這個(gè)構(gòu)造器中,沒有顯式賦值的字段,都會(huì)由編譯器增加一句賦值代碼,將該字段賦值為設(shè)定的默認(rèn)值。其實(shí),無論我們是否給字段增加了默認(rèn)值,字段都具備默認(rèn)值的,只不過如果我們沒有人為增加默認(rèn)值,字段的默認(rèn)值將是0或null。C#語言第一部分面向?qū)ο螅ㄎ澹├^承在現(xiàn)實(shí)生活中,類和類之間可能會(huì)有一種這樣的關(guān)系:一個(gè)類是另一個(gè)類的擴(kuò)展,反過來講,后一個(gè)類是前一個(gè)類的基礎(chǔ)。例如:動(dòng)物類是貓類的基礎(chǔ),貓類是動(dòng)物類的擴(kuò)展。這種關(guān)系稱為繼承,即貓類繼承了動(dòng)物類。被繼承的類稱為父類(C++說法),基類(C#說法)或超類(Java說法),另一個(gè)類叫做子類。怎么叫無所謂,關(guān)鍵看效果。所謂擴(kuò)展,就是子類擁有超類的一切特征(包括屬性和方法),而子類還可以在超類的基礎(chǔ)上添加自身的屬性和方法。例如:貓類擁有動(dòng)物類的一切屬性和行為,但貓類還具有自身的屬性(例如長胡子,喵喵叫)和行為(例如磨爪子,抓耗子)。子類雖然擁有超類的一切特征,但并不是說子類可以任意的去訪問繼承下來的這些超類特征,子類只能訪問到超類中訪問修飾符為public或proctected的那部分屬性和方法,其余的屬性和方法無法直接訪問。C#的這種繼承成為無條件繼承,即子類必須繼承超類的所有特性,無法選擇。看代碼:usingSystem;namespace{publicclassPerson{//保存名字的字段//訪問修飾符protected表示被修飾的成員不僅可以被當(dāng)前類訪問,還可以被該類的所有子類訪問,但不能通過對象被其它類訪問。protectedstringname;protectedintage;protectedboolsex;//帶有參數(shù)的構(gòu)造器publicPerson(stringname,intage,boolsex){this.Name=name;this.Age=age;this.sex=sex;}publicstringName{get{return;}set{=value;}}publicintAge{get{returnage;}set{age=value;}}publicboolSex{get{returnsex;}set{sex=value;}}//顯示個(gè)人信息的方法publicvoidShowMe(){Console.WriteLine("姓名:{0},性別:{1},年齡:{2}歲。",this.Name,this.Sex,this.Age);}}//男人類,從Perso類繼承publicclassMan:Person{//構(gòu)造器。//如果超類沒有提供無參數(shù)的默認(rèn)構(gòu)造器,則子類就必須具備構(gòu)造器//子類的構(gòu)造器參數(shù)沒有必要和超類相同,但子類構(gòu)造器必須使用base關(guān)鍵字調(diào)用超類的某個(gè)構(gòu)造器publicMan(stringname,intage):base(name,age,true){}//表示男人抽煙的方法publicvoidSmork(){Console.WriteLine("{0}抽了一根煙",base.Name);}}//女人類,從Person類繼承publicclassWoman:Person{//構(gòu)造器publicWoman(stringname,intage):base(name,age,false){}//表示女人化妝的方法publicvoidMakeup(){Console.WriteLine("{0}化妝完o畢",base.Name);}}classProgram{staticvoidMain(string[]args){Manman=newMan("小張",19);//調(diào)用Man類從Person類繼承的方法man.ShowMe();//調(diào)用Man類自身具有的方法man.Smork();Womanwoman=newWoman("小白",20);//調(diào)用Woman類從Person類繼承的方法woman.ShowMe();//調(diào)用Woman類自身具有的方法woman.Makeup();}}}繼承最直接的好處是:在設(shè)計(jì)類的時(shí)候,如果存在繼承關(guān)系,則可以通過繼承省略大量代碼的書寫。繼承可以將類組成宗系,更符合軟件開發(fā)的思想:組織功能模塊(超類),細(xì)化功能(子類),功能異化(子類)。這句話可能暫時(shí)不好理解,隨著對面向?qū)ο髮W(xué)習(xí)的深入,慢慢去理解這句話的含義??纯丛谲浖_發(fā)中,如何定義一個(gè)基本功能類,然后不斷的繼承它,完成功能的細(xì)化和擴(kuò)展。對于繼承,語法上沒有任何難點(diǎn),關(guān)鍵要理解子類的構(gòu)造器。子類必須要調(diào)用超類的某個(gè)構(gòu)造器,缺省情況下,子類調(diào)用超類的無參默認(rèn)構(gòu)造器,但如果超類中沒有默認(rèn)構(gòu)造器,則必須顯式說明,子類要調(diào)用超類的哪個(gè)構(gòu)造器。參考89、90行代碼。所謂缺省情況,指的是無需使用base關(guān)鍵字顯式調(diào)用超類構(gòu)造器,此時(shí)子類自動(dòng)調(diào)用超類中沒有參數(shù)的那個(gè)構(gòu)造器。C#語言第一部分面向?qū)ο螅┳兞繉ο蟮囊煤苋菀桌斫獾母拍?,直接看代碼,不多說了。

usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespaceEdu.Study.OO.ReferenceRelationship{publicclassPerson{protectedstringname;protectedintage;protectedboolsex;//帶有參數(shù)的構(gòu)造器publicPerson(stringname,intage,boolsex){this.Name=name;this.Age=age;this.sex=sex;}publicstringName{get{return;}set{=value;}}publicintAge{get{returnage;}set{age=value;}}publicboolSex{get{returnsex;}set{sex=value;}}//顯示個(gè)人信息的方法publicvoidShowMe(){Console.WriteLine("姓名:{0},性別:{1},年齡:{2}歲。",this.Name,this.Sex,this.Age);}}//男人類,從Person類繼承publicclassMan:Person{publicMan(stringname,intage):base(name,age,true){}//表示男人抽煙的方法publicvoidSmork(){Console.WriteLine("{0}抽了一根煙",base.Name);}}classProgram{staticvoidMain(string[]args){Manman=newMan("小王",22);man.ShowMe();man.Smork();Personperson=man;//通過ShowMe執(zhí)行結(jié)果可以看到,person變量實(shí)際上就是前面實(shí)例化的Man類對象//從這個(gè)結(jié)果我們可以看出,無論是前面的man變量,還是person變量,保存的都是一個(gè)實(shí)際對象的引用,對象客觀存在,變量只是給這個(gè)對//象賦予的一個(gè)代稱,一個(gè)對象可以擁有多個(gè)代稱,即一個(gè)對象可以被多個(gè)變量引用,例如://Manman2=man;//此時(shí),定義的新變量man2,它和man變量具有相同的引用person.ShowMe();//Personperson=man這句代碼表達(dá)了一個(gè)很容易理解的說法,男人是人。這種說法隱含了這樣的含義:使用超類定義的變量可以“引用”到某一個(gè)子類實(shí)例化的對象上//反過來呢?人是男人?這種說法顯然是不通的,除非我們確定我們所說得人確實(shí)是一個(gè)男人,所以man=(Man)person;/*這里我們應(yīng)用了C語言風(fēng)格的類型轉(zhuǎn)換運(yùn)算,由于事先已經(jīng)知道person變量確確實(shí)實(shí)是引用到Man類對象的變量,所以//可以將其轉(zhuǎn)換為Man類的變量//person.Smork();//試著將上面這句話的注釋刪掉,這時(shí)候會(huì)發(fā)生一個(gè)編譯錯(cuò)誤。Smork方法無效。這里注意,雖然我們確定person變量//引用著Man類的對象,但person變量的類型依舊是Person類,而Person類是沒有smork方法的*/}}}C#語言第一部分面向?qū)ο螅ㄆ撸┓椒ㄖ剌d一只狼狗無憂無慮的走在大街上,狼狗天性好斗,所以應(yīng)該有一個(gè)Fight方法。這時(shí)候他碰到了一只小狗,即Puppy類的一個(gè)對象,此時(shí)狼狗調(diào)用Fight方法,將這只puppy作為參數(shù)傳入,將其狠狠修理了一頓。不一會(huì)兒,它又碰到一只大狗,很兇惡的樣子,此時(shí)狼狗的心里沒有必勝的把握,但它依舊調(diào)用了Fight方法,將大狗作為參數(shù)傳入。不過這次,F(xiàn)ight方法只是示威了一下而已,叫了幾聲,然后就結(jié)束了。又過了一會(huì)兒,它碰到了一大群狗,即一個(gè)狗數(shù)組,此時(shí)狼狗嚇得屁滾尿流,但還是調(diào)用了Fight方法,將狗數(shù)組作為參數(shù)傳入。這次,F(xiàn)ight方法執(zhí)行的結(jié)果,狼狗逃之夭夭了??梢?,在我們現(xiàn)實(shí)生活中,總是存在這樣一種情況:某類對象的某種行為,因?yàn)橥饨鐥l件不同(參數(shù)不同),執(zhí)行的具體流程也不同。體現(xiàn)在編程代碼中,就是方法的重載。在同一個(gè)類(或某個(gè)類和它的子類)中,一系列同名的方法就構(gòu)成了“重載”,重載的條件是:方法名相同,參數(shù)列表不同。對于子類要重載超類方法的情況,超類該方法必須為protected或public類型??创a:usingSystem;namespace{publicclassPerson{protectedstringname;protectedintage;protectedboolsex;//帶有參數(shù)的構(gòu)造器publicPerson(stringname,intage,boolsex){this.Name=name;this.Age=age;this.sex=sex;}publicstringName{get{return;}set{=value;}}publicintAge{get{returnage;}set{age=value;}}publicboolSex{get{returnsex;}set{sex=value;}}//顯示個(gè)人信息的方法publicvoidShowMe(){Console.WriteLine("姓名:{0},性別:{1},年齡:{2}歲。",this.Name,this.Sex,this.Age);}}publicclassMan:Person{publicMan(stringname,intage):base(name,age,true){}publicvoidSmork(){Console.WriteLine("{0}抽了一根煙",base.Name);}}publicclassWoman:Person{publicWoman(stringname,intage):base(name,age,false){}publicvoidMakeup(){Console.WriteLine("{0}化妝完畢",base.Name);}}publicclassToilet{//廁所進(jìn)入方法,參數(shù)為Man類型publicvoidComming(Manman){Console.WriteLine("{0}進(jìn)?了¢?男D廁T所¨′",man.Name);man.Smork();}//廁所進(jìn)入方法,參數(shù)為Woman類型publicvoidComming(Womanwomen){Console.WriteLine("{0}進(jìn)?了¢?女?廁T所¨′",women.Name);women.Makeup();}}classProgram{staticvoidMain(string[]args){//實(shí)例化廁所對象Toiletwc=newToilet();//實(shí)例化一個(gè)男人和一個(gè)女人Manwang=newMan("小王",22);Womanli=newWoman("小麗",19);//調(diào)用廁所類的Comming方法,分別傳入Man類型變量和Woman類型變量wc.Comming(wang);wc.Comming(li);//可以發(fā)現(xiàn),通過方法的參數(shù),C#編譯器會(huì)自動(dòng)匹配最合適的方法進(jìn)行調(diào)用。//方法重載可以使用同一個(gè)方法名,對傳入不同參數(shù)的各種調(diào)用場景進(jìn)行自動(dòng)適應(yīng)//重載的要點(diǎn):方法名相同,參數(shù)列表不同}}}

熟練應(yīng)用重載,雖然它并不能直接簡化類的編程,但對于調(diào)用這個(gè)類的程序開發(fā)人員來說,重載則更好理解,也更直觀。前面我們講過,只要參數(shù)列表不同,一個(gè)類可以擁有多個(gè)構(gòu)造器。構(gòu)造器的本質(zhì)還是方法,所以多個(gè)構(gòu)造器實(shí)際上還是構(gòu)成了方法的重載。C#語言第一部分面向?qū)ο螅ò耍┓椒ǖ某橄蠛皖惖某橄螽?dāng)我們對客觀事物進(jìn)行分類時(shí),常常會(huì)遇到這樣一個(gè)問題:有一些類并不知道自己的某些方法具體的實(shí)施流程是什么。這樣的類非常多,例如有一個(gè)Person類,其必然有一個(gè)Speak方法,因?yàn)樗械腜erson都可以Speak,但當(dāng)我們設(shè)計(jì)Person類時(shí),卻無法寫出Speak方法體內(nèi)的一行代碼。因?yàn)镻erson類太概括了,如果不明確的指出是哪一國人,我們無法得知Speak方法具體怎么發(fā)生。一個(gè)類,具有某個(gè)行為,但無法得知該行為的具體流程。這樣的行為稱為抽象行為,體現(xiàn)在代碼中就是“抽象方法”。好了,現(xiàn)在我們有一個(gè)擁有抽象方法的類,那當(dāng)我們試圖生成這個(gè)類的實(shí)例時(shí),矛盾就產(chǎn)生了。實(shí)例一旦生成,就表明它是一個(gè)客觀存在的具體事物,不可能存在尚未確定的方法。所以一旦一個(gè)類中具備抽象的方法,則這個(gè)類被稱為“抽象類”。抽象類無法實(shí)例化對象,這是規(guī)定。抽象是面向?qū)ο笳Z言的類得以連續(xù)繼承的關(guān)鍵。OK,總結(jié)一下:超類定義了兩部分方法,一部分方法,超類知道其執(zhí)行流程,這部分方法要么被子類直接繼承,要么被子類繼承后覆蓋;一部分方法,超類并不知道其具體執(zhí)行流程,所以超類給出定義,由知道其具體執(zhí)行流程的那個(gè)子類來覆蓋實(shí)現(xiàn)該方法。好了,我們來舉個(gè)例子:usingSystem;namespace{//依舊創(chuàng)建一個(gè)人類,這次這個(gè)類是“抽象”的,abstract關(guān)鍵字表示抽象publicabstractclassPerson{privatestringname;privateintage;privateboolsex;publicPerson(stringname,intage,boolsex){this.Name=name;this.Age=age;this.sex=sex;}publicboolSex{get{returnsex;}}publicintAge{get{returnage;}set{age=value;}}publicstringName{get{returnname;}set{name=value;}}//去廁所的方法(抽象),abstract關(guān)鍵字表示方法抽象publicabstractvoidGoToilet();}publicclassMan:Person{publicMan(stringname,intage):base(name,age,true){}publicvoidSmork(){Console.WriteLine("{0}抽了一支煙。",this.Name);}//去廁所的方法(實(shí)現(xiàn)超類抽象方法,注意要使用override關(guān)鍵字)publicoverridevoidGoToilet(){Console.WriteLine("{0}解決了燃眉之急。",this.Name);this.Smork();}}publicclassWoman:Person{publicWoman(stringname,intage):base(name,age,false){}publicvoidMakeup(){Console.WriteLine("{0}化妝完畢。",this.Name);}//女人去廁所方法(實(shí)現(xiàn)超類抽象方法,注意要使用override關(guān)鍵字)publicoverridevoidGoToilet(){Console.WriteLine("{0}解決了燃眉之急。",this.Name);this.Makeup();}}publicclassTolite{//進(jìn)入廁所的方法publicvoidComming(Personperson){person.GoToilet();}}classProgram{staticvoidMain(string[]args){//一旦成為抽象類,則無法實(shí)例化對象//Personperson=newPerson("小張",22,true);//定義一男一女Manzhang=newMan("小張",22);Womanli=newWoman("小麗",18);//定義廁所對象Tolitetolite=newTolite();//一男一女去廁所tolite.Comming(zhang);tolite.Comming(li);}}}可以看到,子類一旦繼承了一個(gè)抽象類,就應(yīng)該實(shí)現(xiàn)超類中的抽象方法,使子類得以能夠創(chuàng)建實(shí)例。但如果子類確定無法實(shí)現(xiàn)超類中定義的抽象方法,則子類也必須作為一個(gè)抽象類存在,因?yàn)樽宇惱^承了一個(gè)抽象方法,但卻沒有能夠覆蓋它,給其提供方法體。一般而言,抽象類中必然存在抽象的方法。但對于一個(gè)沒有抽象方法的類,也可以使用abstract關(guān)鍵字聲明其為抽象類,此時(shí)這種聲明方法僅僅是為了阻止這個(gè)類實(shí)例化,指明這個(gè)類必須被繼承而已。C#語言第一部分面向?qū)ο螅ň牛┓椒ǖ某橄蠛皖惖某橄缶毩?xí)(一)上一章我們講了方法和類的抽象,這一章我們從一些例子,繼續(xù)加深對抽象的理解。第一個(gè)例子,我們定義了形狀類(Shap類),從類名字就可以看出該類必然是一個(gè)抽象類。形狀……本來就很抽象嘛。好了,既然是形狀,就必然有面積,Shap類的Area方法必然是一個(gè)抽象方法。接下來,我們創(chuàng)建一個(gè)子類:正多邊形類(Polygon類),繼承自Shap類。這個(gè)類比形狀類具體多了,我們知道了一個(gè)新的屬性:邊長。但只知道邊長依舊無法求出形狀的面積,所以其繼承下來的Area方法依舊只能作為抽象方法,所以Polygon類仍是一個(gè)抽象類。最后,定義正四邊形類和正五邊形類,這兩個(gè)類顯然非常具體了,可以定義Area方法了。就這樣看代碼:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespace{publicabstractclassShap{//定義抽象方法,求面積,對于形狀類,面積方法沒有方法體//<returns>面積</returns>publicabstractdoubleArea();}//定義多邊形類,此類繼承了Area方法,但并未實(shí)現(xiàn),所以依舊抽象類publicabstractclassPolygon:Shap{//邊長字段privatedoublesideLength;//構(gòu)造器,輸入邊長publicPolygon(doublesideLength){this.SideLength=sideLength;}//邊長屬性publicdoubleSideLength{get{returnsideLength;}set{if(value>0){sideLength=value;}else{Console.WriteLine("邊長必須大于0。");}}}}//定義正方形類,繼承自多邊形類(Polygon類)publicclassSquare:Polygon{publicSquare(doublesideLength):base(sideLength){}//求正方形面積,實(shí)現(xiàn)超類的抽象方法publicoverridedoubleArea(){returnMath.Pow(this.SideLength,2);}}//定義五邊形類publicclassPentagon:Polygon{publicPentagon(doublesideLength):base(sideLength){}//求五邊形面積,這里使用工程計(jì)算求近似值,即邊長的平方乘以系數(shù)1.72publicoverridedoubleArea(){returnMath.Pow(this.SideLength,2)*1.72F;}}classProgram{staticvoidMain(string[]args){//使用Shap類變量引用到Square類實(shí)例上Shapshap=newSquare(10);//輸出面積結(jié)果Console.WriteLine("面?積y={0}",shap.Area());//使用Shap類變量引用到Pentagon類實(shí)例上shap=newPentagon(10);//輸出面積Console.WriteLine("面?積y={0}",shap.Area());}}}C#語言第一部分面向?qū)ο螅ň牛┓椒ǖ某橄蠛皖惖某橄缶毩?xí)(二)我們繼續(xù),下面的例子展示了抽象的屬性,我們說過,一個(gè)對象的屬性由一組get/set方法來表現(xiàn),所以屬性也可以作為抽象存在。下面的例子我們定義了Person類,其EyeColor屬性為一個(gè)抽象屬性,由其子類來具體定義??创a:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespace{publicabstractclassPerson{privatestringname;publicPerson(stringname){

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論