C# Ch5面向對象的高級程序設計_第1頁
C# Ch5面向對象的高級程序設計_第2頁
C# Ch5面向對象的高級程序設計_第3頁
C# Ch5面向對象的高級程序設計_第4頁
C# Ch5面向對象的高級程序設計_第5頁
已閱讀5頁,還剩54頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第五章面向對象的高級程序設計

1.總體要求掌握靜態類與靜態類成員的定義與使用。理解類的繼承性與多態性,掌握其應用方法。理解抽象類、接口的概念,掌握抽象類與接口的定義及使用方法。理解嵌套類、分部類和命名空間的概念,掌握嵌套類、分部類和命名空間的使用方法。2.相關知識點熟悉C#的結構、類、數組的區別。熟悉類和類成員的定義與使用熟悉方法的定義與使用等基本操作。3.學習重點靜態成員與靜態類類的繼承性與多態性抽象類與接口定義與使用。4.學習難點靜態成員的作用,靜態方法和實例方法的區別多態的概念和實現,虛方法和抽象方法的區別接口的作用和使用,抽象方法和接口的區別第五章面向對象的高級程序設計第五章面向對象的高級程序設計主要內容5.1靜態成員與靜態類5.2類的繼承性與多態性5.3抽象類與接口5.4嵌套類、分部類與命名空間5.1靜態成員與靜態類

5.1.1靜態成員5.1.2靜態構造函數5.1.3靜態類返回5.1.1靜態成員

靜態成員通過static關鍵字來標識,可以是靜態方法、字段、屬性或事件。靜態成員與非靜態成員的不同在于:靜態成員屬于類,而不屬于類的實例,因此需要通過類而不是通過類的實例來訪問;而非靜態成員則總是與特定的實例(對象)相聯系。在實際應用中,當類的成員所引用或操作的信息是關于類而不是類的實例時,就應該設置為靜態成員。例如,想統計同類對象的數量,就可使用靜態字段和靜態方法來實現5.1.1靜態成員

【實例5-1】利用靜態成員統計人數。5.1.2靜態構造函數類的構造函數也可以是靜態的,靜態構造函數不是為了創建對象而設計的,而是用來初始化類,只有非靜態的構造函數才用來創建對象(用于創建對象的構造函數稱為實例構造函數)。由于靜態構造函數并不對類的特定實例進行操作,所以也稱為全局或共享構造函數。在C#應用程序中,不能直接調用靜態構造函數。靜態構造函數在類的第一個實例創建之前或者調用類的任何靜態方法之前執行,而且最多執行一次。因此,靜態構造函數適合于對類的靜態數據成員進行初始化。5.1.2靜態構造函數靜態構造函數可以與實例構造函數共存,其一般形式如下:static靜態構造函數名(){//語句;}其中,靜態構造函數名與類名相同,聲明靜態構造函數時不能帶訪問修飾符(如public),并且不能有任何參數列表和返回值。5.1.2靜態構造函數我們可以在【實例5-1】的基礎上增加一個靜態構造函數,結果就會不同5.1.3靜態類靜態類使用static關鍵字來聲明,以指示它僅包含靜態成員,不能使用new關鍵字創建靜態類的實例。在實際應用中,當類中的成員不與特定對象關聯的時候,就可以把它創建為靜態類。靜態類有下以特點:(1)靜態類僅包含靜態成員;(2)靜態類不能被實例化;(3)靜態類是密封的;(4)靜態類不能包含實例構造函數5.1.3靜態類由于靜態類是密封的,因此不可被繼承。靜態類不能包含實例構造函數,但仍可聲明靜態構造函數,以分配初始值或設置某個靜態狀態。(關于密封和繼承將在下節進行討論)。靜態類的優點如下:(1)編譯器能夠自動執行檢查,以確保不添加實例成員;(2)靜態類能夠使程序的實現更簡單、迅速,因為不必創建對象就能調用其方法。5.2類的繼承性與多態性5.2.1類的繼承性5.2.2類的多態性返回5.2.1類的繼承性當一個類從另一個類派生出來時,派生類就具有了基類中的所有成員,這樣,基類中定義這些成員的代碼,不需要在派生類定義中重寫,在派生類定義中,只需定義派生類自己的成員即可。這樣,既提高了代碼的重用性,從而提高了程序設計的效率,又提供了已有程序設計的可擴展性。類的繼承為面向對象程序設計構建一個分層類結構體系創造了條件,而.NET框架類庫就是一個龐大的分層類結構體系。其中Object類是一個最上層的基類,其他所有類都是直接或間接由Object類繼承而來的。即使用戶自定義的類沒有指定繼承關系,系統仍然將該類作為Object類的派生類。5.2.1類的繼承性在C#中,類的繼承遵循以下原則:(1)派生類只能從一個類中繼承,即單繼承。(2)派生類自然繼承基類的成員,但不能繼承基類的構造函數(3)類的繼承可以傳遞,例如:假設類C繼承于類B,類B又繼承類A,那么C類即具有類B和類A的成員,可以認為類A是類C的祖先類。5.2.1類的繼承性1.派生類的聲明在C#中,派生類可以擁有自己的成員,也可以隱式地從它的基類繼承所有成員,包括方法、字段、屬性和事件,但私有成員、構造函數和析構函數等除外。另外,派生類只能從一個類中繼承,即單繼承。C#中聲明派生類的一般形式如下:[訪問修飾符]class類名[:基類名]{

類的成員;}5.2.1類的繼承性2.構造函數的調用在C#中,派生類不能繼承其基類的構造函數,但是,在創建對象時,會調用構造函數,為對象分配內存并初始化對象的數據。創建派生類對象時,為完成其基類部份的成員初始化,會調用基類的構造函數。其調用構造函數的順序是先調用基類構造函數,再調用派生類的構造函數,以完成數據成員分配內存空間并進行初始化的工作。類的繼承可以傳遞,例如:假設類C繼承于類B,類B又繼承類A,那么C類即具有類B和類A的成員,可以認為類A是類C的祖先類。在這種情況下,構造函數的調用次序按由高到低順序依次調用,即先調用A的構造函數,再調用B的構造函數。最后調用C的構造函數。5.2.1類的繼承性publicclassA{publicA(){}}publicclassB:A{publicB(){}}5.2.1類的繼承性新類(即派生類)將獲取基類的所有非私有數據和行為以及新類為自己定義的所有其他數據或行為。因此,新類具有兩個有效類型:新類的類型和它繼承的類的類型。在上面的示例中,類B既是有效的B,又是有效的A。訪問B對象時,可以使用強制轉換操作將其轉換為A對象。強制轉換不會更改B對象,但您的B對象視圖將限制為A的數據和行為。將B強制轉換為A后,可以將該A重新強制轉換為B。并非A的所有實例都可強制轉換為B,只有實際上是B的實例的那些實例才可以強制轉換為B。如果將類B作為B類型訪問,則可以同時獲得類A和類B的數據和行為。5.2.1類的繼承性【實例5-2】繼承中的構造函數調用演示。5.2.1類的繼承性如果把基類的構造函數publicAnimal()改為如下形式:publicAnimal(stringname,intage){=name;this.age=age;}則編譯時如出現“Animal不包含采用0個參數的構造函數”的錯誤,這是因為當創建派生類對象時,系統默認調用基類的默認構造函數(即無參構造函數),而當基類沒有默認構造函數或想調用基類的帶參的構造函數時,需要使用base關鍵字。其格式如下:public派生類構造函數名(形參列表):base(向基類構造函數傳遞的形參列表){}5.2.1類的繼承性【實例5-3】調用基類帶參構造函數演示。5.2.1類的繼承性3.密封類為了阻止一個類的代碼被其他類繼承,可以使用密封類,因為在.NET中,加載密封類時將對密封類的方法調用進行優化,因此使用密封類可以提高應用程序的可靠性和性能。另外,軟件開發者通過使用密封類還可以把自己的知識產權保護起來,避免他人共享代碼。在C#中,添加關鍵字sealed可以聲明密封類。5.2.2類的多態性多態性是面向對象程序設計的一個重要特征,多態的意思是一種事物有多種形態,即對象可以表示多個類型的能力稱為多態性。如:通過繼承,一個類可以用作多種類型:可以用作它自己的類型、任何基類型,或者在實現接口時用作任何接口類型。這稱為多態性。多態性不僅對派生類很重要,對基類也很重要。任何情況下,使用基類實際上都可能是在使用已強制轉換為基類類型的派生類對象。基類的設計者可以預測到其基類中可能會在派生類中發生更改的方面。例如,表示汽車的基類可能包含這樣的行為:當考慮的汽車為小型貨車或敞篷汽車時,這些行為將會改變。5.2.2類的多態性當派生類從基類繼承時,它會獲得基類的所有方法、字段、屬性和事件。為了使用派生類能更改基類的數據和行為,C#提供了兩種選擇:一是使用新的派生成員替換基成員,二是重寫虛擬的基成員。5.2.2類的多態性1.使用new關鍵字重新定義類的成員使用new關鍵字來定義與基類中同名的成員,即可替換基類的成員。如果基類定義了一個方法、字段或屬性,則new關鍵字用于在派生類中創建該方法、字段或屬性的新定義。new關鍵字應放置在要替換的類成員的返回類型之前。使用new

關鍵字時,調用的是新的類成員而不是已被替換的基類成員。這些基類成員稱為隱藏成員。如果將派生類的實例強制轉換為基類的實例,就仍然可以調用隱藏類成員。5.2.2類的多態性2.為了使派生類的實例完全接替來自基類的類成員,基類必須將該成員聲明為虛擬的。通過在該成員的返回類型之前添加virtual關鍵字來實現的。然后,派生類可以選擇使用override關鍵字而不是new,將基類實現替換為它自己的實現。用virtual和override關鍵字定義類成員基類中的聲明格式:publicvirtual方法名稱([參數列表]){}派生類的聲明格式:publicoverride方法名稱([參數列表]){}其中,基類與派生類中的方法名稱與參數列表必須完全一致。5.2.2類的多態性【實例5-4】虛方法演示。5.2.2類的多態性當點擊“創建子類對象并調用方法”按鈕時,以子類對象做為實參,將調用子類的Eat方法,顯示結果會不同無論在派生類和最初聲明虛成員的類之間已聲明了多少個類,虛成員都將永遠為虛成員。如果類A聲明了一個虛擬成員,類B從A派生,類C從類B派生,則類C繼承該虛擬成員,并且可以選擇重寫它,而不管類B是否為該成員聲明了重寫。例如:publicclassA{publicvirtualvoidDoWork(){}}publicclassB:A{publicoverridevoidDoWork(){}}publicclassC:B{publicoverridevoidDoWork(){}}5.2.2類的多態性派生類可以通過將重寫聲明為密封的來停止虛擬繼承。這需要在類成員聲明中將sealed關鍵字放在override關鍵字的前面。publicclassC:B{publicsealedoverridevoidDoWork(){}}在上面的示例中,方法DoWork對從C派生的任何類都不再是虛方法,但它仍是C的實例的虛方法--即使將這些實例強制轉換為類型B或類型A也是如此。派生類可以通過使用new關鍵字替換密封的方法,如下面的示例所示:publicclassD:C{publicnewvoidDoWork(){}}在此情況下,如果在D中使用類型為D的變量調用DoWork,被調用的將是新的DoWork。如果使用類型為C、B或A的變量訪問D的實例,對DoWork的調用將遵循虛擬繼承的規則,即把這些調用傳送到類C的DoWork實現。5.2.2類的多態性使用virtual和override時要注意以下幾點:(1)字段不能是虛擬的,只有方法、屬性、事件和索引器才可以是虛擬的;(2)使用virtual修飾符后,不允許再使用static、abstract或override修飾符;(3)派生類對象即使被強制轉換為基類對象,所引用的仍然是派生類的成員;(4)派生類可以通過密封來停止虛擬繼承,此時派生類的成員使用sealedoverride聲明。5.2.2類的多態性3.調用基類方法當派生類重載或覆蓋基類方法后,如果想調用基類的同名方法,可以使用base關鍵字。如,在Dog類的Eat方法中,希望使用基類的Eat方法,可以用如下方法:publicoverridevoidEat(){base.Eat();}5.3抽象類與接口5.3.1抽象類5.3.2接口5.3.3抽象類與接口的比較返回5.3.1抽象類

抽象方法是指在基類的定義中,不包含任何實現代碼的方法,實際上就是一個不具有任何具體功能的方法。這樣的方法唯一的作用就是讓派生類重寫。而只要在類中包含一個抽象方法,該類即為抽象類。在抽象類中,也可以聲明非抽象方法。1.抽象類與抽象方法的聲明在C#中,抽象類和抽象方法使用關鍵字abstract聲明,一般形式如下:publicabstractclass抽象類名{[訪問修飾符]abstract返回值類型方法名([參數列表])}5.3.1抽象類抽象類具有以下特性:抽象類不能實例化。抽象類可以包含抽象方法和抽象訪問器。不能用sealed修飾符修改抽象類,這意味著抽象類不能被繼承。從抽象類派生的非抽象類必須包括繼承的所有抽象方法和抽象訪問器的實實現。在方法或屬性聲明中使用abstract

修飾符以指示方法或屬性不包含實現。抽象方法具有以下特性:抽象方法是隱式的虛方法。只允許在抽象類中使用抽象方法聲明。因為抽象方法聲明不提供實際的實現,所以沒有方法體;方法聲明只是以一個分號結束,并且在簽名后沒有大括號({})。5.3.1抽象類實現由一個重寫方法override提供,此重寫方法是非抽象類的一個成員。在抽象方法聲明中使用static或virtual修飾符是錯誤的。除了在聲明和調用語法上不同外,抽象屬性的行為與抽象方法一樣。在靜態屬性上使用abstract

修飾符是錯誤的。在派生類中,通過包括使用override修飾符的屬性聲明,可以重寫抽象的繼承屬性。5.3.1抽象類抽象類中也可以有抽象屬性。類的屬性成員添加了abstract關鍵字后,就成了抽象屬性。抽象屬性不提供屬性訪問器的實現,它只聲明該類支持的屬性,而將訪問器的實現留給派生類。抽象屬性同樣可以是只讀的、只寫的或可讀寫的屬性。一般形式如下:publicabstract返回值類型屬性名{get;set;}抽象類可以包含抽象的成員,如抽象屬性和抽象方法,也可以包含非抽象的成員,甚至還可以包含虛方法。要注意的是,抽象成員必須在抽象類中聲明,但抽象類不要求必須包含抽象成員5.3.1抽象類2.重載抽象方法抽象類中的抽象方法和抽象屬性都沒有提供實現,當定義抽象類的派生類時,派生類必須重載基類的抽象方法和抽象屬性(如果派生類沒有進行重載,則派生也必須聲明為抽象類,即在類定義前加上abstract。這一點是與虛方法不同的,因為對于基類的虛方法,其派生類可以不重載。重載抽象類的方法和屬性必須使用override關鍵字。重載抽象方法的格式為:publicoverride方法名稱([參數列表]){}其中,方法名稱和參數列表必須與抽象類中的抽象方法完全一致。當抽象類從基類繼承虛方法時,抽象類可以使用抽象方法重寫該虛方法。例如://compilewith:/target:librarypublicclassD{publicvirtualvoidDoWork(inti){//Originalimplementation.}}publicabstractclassE:D{publicabstractoverridevoidDoWork(inti);}publicclassF:E{publicoverridevoidDoWork(inti){//Newimplementation.}}如果將虛方法聲明為抽象方法,則它對于從抽象類繼承的所有類而言仍然是虛的。繼承抽象方法的類無法訪問該方法的原始實現。在前面的示例中,類F上的DoWork無法調用類D上的DoWork。在此情況下,抽象類可以強制派生類為虛方法提供新的方法實現。5.3.1抽象類【實例5-5】抽象方法和抽象類演示。5.3.2接口接口(interface)是C#的一種數據類型,屬于引用類型。一個接口定義一個協定。接口可以包含方法、屬性、事件和索引器,接口本身不提供它所定義的成員的實現,接口只指定實現該接口的類或結構必須提供的成員。實現某接口的類必須遵守該接口定義的協定,即必須提供接口成員的實現。1.接口的聲明在C#中,聲明接口使用interface關鍵字,一般形式如下:[訪問修飾符]interface接口名[:基接口列表]{//接口成員}5.3.2接口接口成員可以是屬性、方法、索引器和事件,不能包含字段、構造函數等。所有接口成員隱式地具有了public訪問修飾符,因此,接口成員不能添加任何訪問修飾符。下面示例定義了一個USB的接口,該接口包含了一個TransData方法簽名和一個獲到最大傳輸速率的只讀屬性。。interfaceIUsb{intMaxSpeed{get;}stringTransData(stringfrom,stringto);}5.3.2接口2.接口的實現接口主要用來定義一個規則,讓企業內部或行業內部的軟件開發人員按標準去實現應用程序的功能。因此,繼承接口的類或結構必須實現接口中的所有屬性、方法、索引器和事件,繼承接口的方法與繼承類相似3.接口的繼承接口也可以繼承其它接口,而接口可以多繼承,即接口可以從多個接口繼承,基接口名之間用逗號分隔。

5.3.2接口4.多重接口實現C#不允許多重類繼承,但是C#允許多重接口實現,這意味著一個類可以實現多個接口,如果一個Mobile類支持USB,也可以支持Bluetooth,我們就應該同時實現IUsb和IBluetooth接口,在繼承時,兩個接口之間用逗號分隔。其類的頭部如下所示:publicclassMobile:IUsb,IBluetooth如果類Mobile是類phone的派生子類,也可以同時繼承phone類。但要注意,基類必須在所有的接口之前,如:publicclassMobile:Phone,IUsb,IBluetooth5.3.2接口5.訪問接口的方法當類Mp3實現了IUsb后,我們可以通過MP3類的對象訪問IUsb的成員,就好象是Mp3類的成員一樣:Mp3m=newMp3();lblShow.Text=m.TransData("計算機","MP3設備");或者我們也可以將Mp3對象轉換成接口類型,然后用這個接口來訪問方法:Mp3m=newMp3();IUsbiu=(IUsb)m;lblShow.Text=iu.TransData("計算機","MP3設備");5.3.2接口【實例5-6】接口演示。5.3.3抽象類與接口的比較抽象類是一種不能實例化的類,抽象類可以包含抽象成員,也可以包含非抽象成員,即抽象類可以是完全實現的,也可以是部分實現的,或者完全不實現的。抽象類可以用來封裝所有派生類的通用功能。與抽象類不同的是,接口頂多像一個完全沒有實現的只包含抽象成員的抽象類,因此無法使用接口來封裝所有派生類的通用功能,接口更多地用來制定程序設計開發規范,接口的代碼實現由開發者完成。例如,有關XML文檔的處理,萬維網聯盟(W3C)就制定了一個DOM(文檔對象模型)規范,而具體的代碼實現由諸如Microsoft、Sun等公司去實現。5.3.3抽象類與接口的比較C#規定一個類只能從一個基類派生,但允許從多個接口派生。例如,如果把實例5-6中的兩個接口改為抽象類,則不允許同時使用它們來派生Mobile類。抽象類為管理組件版本提供了一個簡單易行的方法。通過更新基類,所有派生類都將自動進行相應改動。而接口在創建后就不能再更改,如果需要修改接口,必須創建新的接口。5.4嵌套類、分部類與命名空間5.4.1嵌套類5.4.2分部類5.4.3命名空間返回5.4.1嵌套類在類的內部或結構的內部定義的類型稱為嵌套類型,又稱內部類型。不論是類還是結構,嵌套類型均默認為private,嵌套類型也可以設置為public、internal、protected或protectedinternal。嵌套類型通常需要實例化為對象之后,才能引用其成員,其使用方法與類的普通成員使用基本相同。【實例5-7】使用嵌套類計算長方形面積。5.4.2分部類分部類允許將類、結構或接口的定義拆分到兩個或多個源文件中,讓每個源文件只包含類型定義的一部分,編譯時編譯器自動把所有部分組合起來進行編譯。有了分部類,一個類的源代碼可以分布于多個獨立文件中,在處理大型項目時,過去很多只能由一個人進行的編程任務,現在可以由多個人同時進行,這樣將大大加快了程序設計的工作進度。有了分部類,使用自動生成的源代碼時,無需重新創建源文件便可將代碼添加到類中。事實上,當創建Windows應用程序或Web應用程序時,就是在VisualStudio2010自動生成源代碼的基礎之上專注于項目的業務處理,編譯時VisualStudio2010會自動把編寫的代碼與自動生成的代碼進行合并編譯。5.4.2分部類處理分部類的定義時需遵循以下幾個規則:(1)同一類型的各個部分的所有分部類的定義都必須使用partial進行修飾。(2)如果將任意部分聲明為抽象的,則整個類型都被視為抽象的。如果將任意部分聲明為密封的,則整個類型都被視為密封的。(3)partial修飾符只能出現在緊靠關鍵字class、struct或interface前面的位置。(4)分部類的各部分或者各個源

溫馨提示

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

評論

0/150

提交評論