面向對象的高級編程_第1頁
面向對象的高級編程_第2頁
面向對象的高級編程_第3頁
面向對象的高級編程_第4頁
面向對象的高級編程_第5頁
已閱讀5頁,還剩23頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、第4章 面向對象的高級編程4.1 封裝、繼承與多態(tài)封裝、繼承與多態(tài) 封裝封裝、繼承繼承與與多態(tài)性多態(tài)性是面向對象編程的是面向對象編程的三大原三大原則則。封裝用于隱藏調(diào)用者不需要了解的信息;繼承。封裝用于隱藏調(diào)用者不需要了解的信息;繼承則簡化了類的設計;多態(tài)性是指類為名稱相同的方則簡化了類的設計;多態(tài)性是指類為名稱相同的方法提供不同實現(xiàn)方式的能力。在實際編程中,只有法提供不同實現(xiàn)方式的能力。在實際編程中,只有深刻理解這些概念,才能更好地利用面向對象技術深刻理解這些概念,才能更好地利用面向對象技術編寫出高質量的程序代碼。編寫出高質量的程序代碼。 第4章 面向對象的高級編程4.1 封裝、繼承與多態(tài)封

2、裝、繼承與多態(tài)4.1.1 4.1.1 封裝性封裝性 在面向對象編程中,封裝是指把數(shù)據(jù)和處理這些數(shù)在面向對象編程中,封裝是指把數(shù)據(jù)和處理這些數(shù)據(jù)的代碼封裝在一個類中,然后通過提供相應的屬性據(jù)的代碼封裝在一個類中,然后通過提供相應的屬性和方法供調(diào)用者使用,通過隱藏調(diào)用者不需要的信息和方法供調(diào)用者使用,通過隱藏調(diào)用者不需要的信息(如實現(xiàn)細節(jié)),可以讓調(diào)用者只關心對象中對其有(如實現(xiàn)細節(jié)),可以讓調(diào)用者只關心對象中對其有用的相關內(nèi)容。用的相關內(nèi)容。 在設計類時,應盡可能隱藏實現(xiàn)的細節(jié),只提供在設計類時,應盡可能隱藏實現(xiàn)的細節(jié),只提供給調(diào)用者需要知道的操作和數(shù)據(jù)。這樣做的好處是當給調(diào)用者需要知道的操作和

3、數(shù)據(jù)。這樣做的好處是當設計者修改實現(xiàn)的細節(jié)時,可以不影響調(diào)用者與類的設計者修改實現(xiàn)的細節(jié)時,可以不影響調(diào)用者與類的 交互方式。交互方式。 例例4-1 4-1 通過屬性進行封裝通過屬性進行封裝using System;using System;using System.Collections.Genericusing System.Collections.Generic; ;using System.Textusing System.Text; ;namespace EncapulationExamplenamespace EncapulationExample class BankAccoun

4、t class BankAccount / /帳戶余額帳戶余額 private decimal accountBalanceprivate decimal accountBalance; ; public decimal AccountBalance public decimal AccountBalance get get return accountBalance return accountBalance; ; public BankAccount(decimal startAmount public BankAccount(decimal startAmount) ) accountB

5、alance=startAmount accountBalance=startAmount; ; /可以通過此方法取款可以通過此方法取款 public void Withdraw(decimalpublic void Withdraw(decimal money) money) if(accountBalance if(accountBalance=money)=money) accountBalance accountBalance-=money;-=money; class Program class Program public static void Main(string args

6、public static void Main(string args) ) BankAccount ZhangSan BankAccount ZhangSan=new BankAccount(1000);=new BankAccount(1000); ZhangSan.Withdraw(100); ZhangSan.Withdraw(100); Console.WriteLine Console.WriteLine(帳戶的余額為帳戶的余額為0:C,ZhangSan.AccountBalance);0:C,ZhangSan.AccountBalance); Console.ReadLine C

7、onsole.ReadLine();(); 第4章 面向對象的高級編程4.1 封裝、繼承與多態(tài)封裝、繼承與多態(tài)4.1.1 4.1.1 繼承繼承 繼承(繼承(InheritanceInheritance)是指類能夠從它的父類中繼承除)是指類能夠從它的父類中繼承除構造函數(shù)以外的所有數(shù)據(jù)的定義和功能。繼承能夠提高代構造函數(shù)以外的所有數(shù)據(jù)的定義和功能。繼承能夠提高代碼的可重用性。通過繼承,使程序員能夠直接享用他人或碼的可重用性。通過繼承,使程序員能夠直接享用他人或自己事先寫好的基類中已有的功能,而不必全部重新編寫。自己事先寫好的基類中已有的功能,而不必全部重新編寫。 在在C#C#語言中,作為基礎的、被

8、繼承的類稱為基類語言中,作為基礎的、被繼承的類稱為基類(Base ClassBase Class),繼承自別的類的子類稱為擴充類),繼承自別的類的子類稱為擴充類(Derived ClassDerived Class,又叫派生類)。,又叫派生類)。 C#C#語言提供了兩種實現(xiàn)繼承的方式:類繼承和接口繼語言提供了兩種實現(xiàn)繼承的方式:類繼承和接口繼承。不過類繼承只允許單一繼承,即只有一個基類。單一承。不過類繼承只允許單一繼承,即只有一個基類。單一基類已經(jīng)能夠滿足大多數(shù)面向對象應用程序開發(fā)上的要求,基類已經(jīng)能夠滿足大多數(shù)面向對象應用程序開發(fā)上的要求,也有效地降低了復雜性。如果必須使用多重繼承,可以通也

9、有效地降低了復雜性。如果必須使用多重繼承,可以通過接口來實現(xiàn)。過接口來實現(xiàn)。 注意:雖然繼承是非常有用的編程概念,但使用不當也會帶來一注意:雖然繼承是非常有用的編程概念,但使用不當也會帶來一些負面的效果。在下列情況下可以使用類繼承。些負面的效果。在下列情況下可以使用類繼承。(1 1)擴充類與基類的關系是)擴充類與基類的關系是“屬于屬于”關系而不是關系而不是“具有具有”關系,或者關系,或者說,擴充類不能是基類的說,擴充類不能是基類的“子集子集”,也不能是只包含基類中的一部分。,也不能是只包含基類中的一部分?!熬哂芯哂小标P系的類不適合使用類繼承,因為這樣可能會繼承不適當?shù)膶傩躁P系的類不適合使用類繼

10、承,因為這樣可能會繼承不適當?shù)膶傩院头椒?。和方法。? 2)可以重用基類的代碼。例如,如果一個數(shù)據(jù)庫中有多個表,對每)可以重用基類的代碼。例如,如果一個數(shù)據(jù)庫中有多個表,對每一個表都設計添加、刪除和修改等功能顯然既費時又容易出錯,這時使用一個表都設計添加、刪除和修改等功能顯然既費時又容易出錯,這時使用類繼承就是比較好的選擇。類繼承就是比較好的選擇。(3 3)需要將相同的類和方法應用到不同的數(shù)據(jù)類型。這時可以利用重)需要將相同的類和方法應用到不同的數(shù)據(jù)類型。這時可以利用重寫基類中的某些方法來實現(xiàn)。寫基類中的某些方法來實現(xiàn)。(4 4)類層次分級比較少,而且其他開發(fā)人員不可能添加太多的級別。)類層次

11、分級比較少,而且其他開發(fā)人員不可能添加太多的級別。繼承最適合于分級相對較少的類層次結構。一般來說,應將層次結構限制繼承最適合于分級相對較少的類層次結構。一般來說,應將層次結構限制在低于在低于6 6級。級。(5 5)需要只修改基類就可以對繼承的類進行全部更改的情況。繼承的)需要只修改基類就可以對繼承的類進行全部更改的情況。繼承的一個最強大的功能是在基類中進行的更改將自動傳播到擴充類中。例如,一個最強大的功能是在基類中進行的更改將自動傳播到擴充類中。例如,更新一個方法的實現(xiàn),從而幾十甚至上百個擴充類都可以自動使用該新代更新一個方法的實現(xiàn),從而幾十甚至上百個擴充類都可以自動使用該新代碼。但是,一般情

12、況下,應避免更改基類成員的名稱或類型,因為這樣容碼。但是,一般情況下,應避免更改基類成員的名稱或類型,因為這樣容易導致使用原成員的擴充類出現(xiàn)問題。易導致使用原成員的擴充類出現(xiàn)問題。 1 1、擴充類、擴充類 要聲明一個擴充類,可以使用下面的語法:要聲明一個擴充類,可以使用下面的語法: 訪問修飾符訪問修飾符 class class 擴充類名稱擴充類名稱: :基類名稱基類名稱 / /程序代碼程序代碼 擴充類繼承了所有定義在基類中數(shù)據(jù)的定義擴充類繼承了所有定義在基類中數(shù)據(jù)的定義和方法。但是要注意,構造函數(shù)則排除在外,不會和方法。但是要注意,構造函數(shù)則排除在外,不會被繼承下來,而且擴充類不繼承基類的數(shù)據(jù)

13、值。被繼承下來,而且擴充類不繼承基類的數(shù)據(jù)值。 例例4-2 4-2 類和繼承。類和繼承。using System;using System;namespace InheritanceExamplenamespace InheritanceExample public class Animal public class Animal public Animal() public Animal() Console.WriteLine(Hello,Animal Console.WriteLine(Hello,Animal!);!); public Animal(string public Anima

14、l(string name) name) Console.WriteLine(Hello,My name is+name Console.WriteLine(Hello,My name is+name+!);+!); public void Eat() public void Eat() Console.WriteLine(Eating Console.WriteLine(Eating);); public class Cat:Animalpublic class Cat:Animal public Cat() public Cat() Console.WriteLine(Hello,Cat

15、Console.WriteLine(Hello,Cat!);!); class Program class Program static void Main(string args static void Main(string args) ) Cat e=new Cat(); Cat e=new Cat(); e.Eat e.Eat();(); Console.ReadLine Console.ReadLine();(); 不過,擴充類并不一定能夠直接使用基類中所定義的所有不過,擴充類并不一定能夠直接使用基類中所定義的所有數(shù)據(jù)與方法,如基類的數(shù)據(jù)與方法,如基類的publicpublic成員將

16、會成為擴充類的成員將會成為擴充類的publicpublic成員,成員,publicpublic表示允許外部類自由地調(diào)用;而基類的表示允許外部類自由地調(diào)用;而基類的privateprivate成員則只成員則只會被基類本身的成員存取,擴充類無法使用基類的會被基類本身的成員存取,擴充類無法使用基類的privateprivate成員。成員。 類類CatCat繼承自類繼承自類AnimalAnimal,當創(chuàng)建,當創(chuàng)建CatCat的實例時,會先調(diào)用基類的實例時,會先調(diào)用基類的構造函數(shù),然后調(diào)用擴充類的構造函數(shù),因此輸出結果為:的構造函數(shù),然后調(diào)用擴充類的構造函數(shù),因此輸出結果為:2 2、密封類、密封類 密封

17、類是指不能被其他類繼承的類。在密封類是指不能被其他類繼承的類。在C#C#語言中,使用語言中,使用sealedsealed關鍵字聲明密封類。由于密封類不能被其他類繼承,因關鍵字聲明密封類。由于密封類不能被其他類繼承,因此系統(tǒng)在運行時就可以對密封類的方法進行優(yōu)化,從而提高系此系統(tǒng)在運行時就可以對密封類的方法進行優(yōu)化,從而提高系統(tǒng)的性能。統(tǒng)的性能。 同樣,同樣,sealedsealed關鍵字也可以限制基類中的方法被擴充類關鍵字也可以限制基類中的方法被擴充類重寫。例如,下面的程序代碼是錯誤的。重寫。例如,下面的程序代碼是錯誤的。 例例4-34-3錯誤的用法。錯誤的用法。 using System;us

18、ing System;namespace SealExamplenamespace SealExample public sealed class Hello public sealed class Hello public void SayHello public void SayHello()() Console.WriteLine Console.WriteLine(這是基類這是基類);); class Program:Hello class Program:Hello static void Main(string args static void Main(string args)

19、) Hello me=new Hello(); Hello me=new Hello(); me.SayHello me.SayHello();(); Console.ReadLine Console.ReadLine();(); 4.1.3 4.1.3 多態(tài)性多態(tài)性 多態(tài)性是指類為名稱相同的方法提供不同實現(xiàn)方式的能力。多態(tài)性是指類為名稱相同的方法提供不同實現(xiàn)方式的能力。利用多態(tài)性,就可以調(diào)用類中的某個方法而無需考慮該方法是如何利用多態(tài)性,就可以調(diào)用類中的某個方法而無需考慮該方法是如何實現(xiàn)的。實現(xiàn)的。 有以下幾種實現(xiàn)多態(tài)性的方式。有以下幾種實現(xiàn)多態(tài)性的方式。第一種方式是通過繼承實現(xiàn)多態(tài)性。多個

20、類可以繼承自同一個類,第一種方式是通過繼承實現(xiàn)多態(tài)性。多個類可以繼承自同一個類,每個擴充類又可根據(jù)需要重寫基類成員以提供不同的功能。每個擴充類又可根據(jù)需要重寫基類成員以提供不同的功能。第二種方式是通過抽象類實現(xiàn)多態(tài)性。抽象類本身不能被實例化,第二種方式是通過抽象類實現(xiàn)多態(tài)性。抽象類本身不能被實例化,只能在擴充類中通過繼承使用。抽象類的部分或全部成員不一定都只能在擴充類中通過繼承使用。抽象類的部分或全部成員不一定都要實現(xiàn),但是要在繼承類中全部實現(xiàn)。抽象類中已實現(xiàn)的成員仍可要實現(xiàn),但是要在繼承類中全部實現(xiàn)。抽象類中已實現(xiàn)的成員仍可以被重寫,并且繼承類仍可以實現(xiàn)其他功能。以被重寫,并且繼承類仍可以實

21、現(xiàn)其他功能。第三種方式是通過接口實現(xiàn)多態(tài)性。多個類實現(xiàn)相同的第三種方式是通過接口實現(xiàn)多態(tài)性。多個類實現(xiàn)相同的“接口接口”,而單個類可以實現(xiàn)一個或多個接口。接口本質上是類需要如何響應而單個類可以實現(xiàn)一個或多個接口。接口本質上是類需要如何響應的定義。接口僅聲明類需要實現(xiàn)的方法、屬性和事件,以及每個成的定義。接口僅聲明類需要實現(xiàn)的方法、屬性和事件,以及每個成員需要接收和返回的參數(shù)類型,而這些成員的特定實現(xiàn)留給實現(xiàn)類員需要接收和返回的參數(shù)類型,而這些成員的特定實現(xiàn)留給實現(xiàn)類去完成。去完成。1 1、虛擬方法、虛擬方法 如果基類提供的功能不能夠滿足要求,而且基類允許重寫,如果基類提供的功能不能夠滿足要求,

22、而且基類允許重寫,則可以在擴充類中重新定義基類的方法。在基類中,如果想讓某個則可以在擴充類中重新定義基類的方法。在基類中,如果想讓某個方法或者事件被擴充類重寫,可以使用修飾符方法或者事件被擴充類重寫,可以使用修飾符 VirtualVirtual表明,例如:表明,例如: public virtual void myMethodpublic virtual void myMethod()() / /程序代碼程序代碼 這樣,在擴充類中就可以使用修飾符這樣,在擴充類中就可以使用修飾符overrideoverride重寫該方法或重寫該方法或者事件了。例如:者事件了。例如: public override

23、 void myMethodpublic override void myMethod()() / /程序代碼程序代碼 在在C#C#語言中,定義的方法默認都是非虛擬的(語言中,定義的方法默認都是非虛擬的(non-non-virtualvirtual), ,即不允許重寫這些方法,但是基類中的方法使用了即不允許重寫這些方法,但是基類中的方法使用了virtualvirtual修飾符以后,該方法就變成了虛擬方法。在擴充類中,修飾符以后,該方法就變成了虛擬方法。在擴充類中,既可以重寫基類的虛擬方法,也可以不重寫。但是要注意,如既可以重寫基類的虛擬方法,也可以不重寫。但是要注意,如果重寫基類的虛擬方法,必

24、須在擴充類中用果重寫基類的虛擬方法,必須在擴充類中用overrideoverride關鍵字聲關鍵字聲明。明。 使用虛擬方法與重寫方法時,需要注意下面幾個方面。使用虛擬方法與重寫方法時,需要注意下面幾個方面。(1 1)虛擬方法不能聲明為靜態(tài)()虛擬方法不能聲明為靜態(tài)(staticstatic)的。因為靜態(tài)的)的。因為靜態(tài)的方法是應用在類這一層次的,而面向對象的多態(tài)性只能在對象方法是應用在類這一層次的,而面向對象的多態(tài)性只能在對象上運作,所以無法在類中使用。上運作,所以無法在類中使用。(2 2)virtualvirtual不能和不能和privateprivate一起使用。因為聲明為一起使用。因為聲

25、明為privateprivate就無法在擴充類中重寫了。就無法在擴充類中重寫了。(3 3)重寫方法的名稱、參數(shù)個數(shù)、類型以及返回值都必須)重寫方法的名稱、參數(shù)個數(shù)、類型以及返回值都必須和虛擬方法的一致。和虛擬方法的一致。 例例4-44-4重寫基類的方法重寫基類的方法using System;using System;namespace OverrideExamplenamespace OverrideExample class Shape class Shape public virtual void ShowShape public virtual void ShowShape()() Co

26、nsole.WriteLine Console.WriteLine(我是圖形我是圖形!);!); class Triangle:Shape class Triangle:Shape public override void ShowShape public override void ShowShape()() base.ShowShape base.ShowShape();(); Console.WriteLine Console.WriteLine(我是三角形我是三角形!);!); class Programclass Program static void Main(string arg

27、s static void Main(string args) ) Triangle me=new Triangle(); Triangle me=new Triangle(); me.ShowShape me.ShowShape();(); Console.ReadLine Console.ReadLine();(); 2 2、隱藏基類的方法、隱藏基類的方法 在擴充類中,可以使用在擴充類中,可以使用newnew關鍵字來隱藏基類關鍵字來隱藏基類的方法,即使用一個完全不同的方法取代舊的方法。的方法,即使用一個完全不同的方法取代舊的方法。 與方法重寫不同的是,使用與方法重寫不同的是,使用newne

28、w關鍵字時并不關鍵字時并不要求基類中的方法聲明為要求基類中的方法聲明為virtualvirtual,只要在擴充類,只要在擴充類的方法前聲明為的方法前聲明為newnew,就可以隱藏基類的方法。,就可以隱藏基類的方法。 例例4-6 4-6 隱藏基類的方法。隱藏基類的方法。using System;using System;namespace ConsealExamplenamespace ConsealExample public class Hello public class Hello public void SayHello public void SayHello()() Console

29、.WriteLine Console.WriteLine(這是基類這是基類!);!); public class NewHello:Hello public class NewHello:Hello public new void SayHello public new void SayHello()() Console.WriteLine Console.WriteLine(這是擴充類這是擴充類!);!); class Programclass Program static void Main(string args static void Main(string args) ) Hello

30、 b=new Hello(); Hello b=new Hello(); b.SayHello b.SayHello();(); NewHello d=new NewHello NewHello d=new NewHello();(); d.SayHello d.SayHello();(); Console.ReadLine Console.ReadLine();(); 什么情況下需要這樣做呢?例如,現(xiàn)在根據(jù)需要什么情況下需要這樣做呢?例如,現(xiàn)在根據(jù)需要要求設計人員要求設計人員A A重新設計基類中的某個方法,該基類一重新設計基類中的某個方法,該基類一年前由另一組設計人員設計的,并且已經(jīng)交給用戶

31、使年前由另一組設計人員設計的,并且已經(jīng)交給用戶使用,可是原來的設計人員在該方法前沒有加用,可是原來的設計人員在該方法前沒有加virtualvirtual關關鍵字,設計人員鍵字,設計人員A A也沒有這些源代碼。這種情況下顯然也沒有這些源代碼。這種情況下顯然不能使用不能使用overrideoverride重寫基類的方法,又無法直接修改重寫基類的方法,又無法直接修改基類的方法,這時就需要隱藏基類的方法?;惖姆椒ǎ@時就需要隱藏基類的方法。 3 3、抽象類、抽象類 抽象類使用抽象類使用abstractabstract修飾符,用于表示所修飾修飾符,用于表示所修飾的類是不完整的,即類中的成員(例如方法)

32、不一定的類是不完整的,即類中的成員(例如方法)不一定全部實現(xiàn),可以只有聲明沒有實現(xiàn)。抽象類只能用做全部實現(xiàn),可以只有聲明沒有實現(xiàn)。抽象類只能用做基類。抽象類與非抽象類相比有以下主要不同之處:基類。抽象類與非抽象類相比有以下主要不同之處:第一是抽象類不能直接被實例化,只能在擴充類中第一是抽象類不能直接被實例化,只能在擴充類中通過繼承使用,對抽象類使用通過繼承使用,對抽象類使用newnew運算符會產(chǎn)生編譯時運算符會產(chǎn)生編譯時錯誤。錯誤。第二個不同點是抽象類可以包含抽象成員,而非抽第二個不同點是抽象類可以包含抽象成員,而非抽象類不能包含抽象成員。當從抽象類派生非抽象類時,象類不能包含抽象成員。當從抽

33、象類派生非抽象類時,這些非抽象類必須具體實現(xiàn)所繼承的所有抽象成員。這些非抽象類必須具體實現(xiàn)所繼承的所有抽象成員。例如:例如:using System;using System;abstract class Aabstract class A public abstract void F(); / public abstract void F(); /抽象方法,注意該方法沒有實現(xiàn)部分抽象方法,注意該方法沒有實現(xiàn)部分 abstract class B:Aabstract class B:A public void G() public void G() class C:Bclass C:B public override void F() public override void F() / /實現(xiàn)部分實現(xiàn)部分 在上面的代碼中,抽象類在上面的代碼中,抽象類A A引入抽象方法引入抽象方法F F。注意:抽。注意:抽象方法均為虛擬方法,不要加象方法均為虛擬方法,不要加virtualvirtual。

溫馨提示

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

最新文檔

評論

0/150

提交評論