日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[.net 面向对象编程基础] (13) 面向对象三大特性——多态

發(fā)布時間:2025/5/22 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [.net 面向对象编程基础] (13) 面向对象三大特性——多态 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

[.net?面向?qū)ο缶幊袒A(chǔ)]?(13)?面向?qū)ο笕筇匦浴?/span>多態(tài)

? ? ? 前面兩節(jié),我們了解了面向?qū)ο蟮牡姆庋b和繼承特性,面向?qū)ο筮€有一大特性就是多態(tài)。比起前面的封裝和繼承,多態(tài)這個概念不是那么好理解。我們還是從一個事例開始:

? ? ? 公司最近為了陶冶情操,養(yǎng)了幾種動物(Animal),有貓(Cat)、狗(Dog)、羊(Sheep),這些動物都有共同的特性,會吃(Eat)、會叫(Shout),但是它們吃的不同,叫的也不同。既然這樣,我們能不能設(shè)計一個動物類(Animal)和它的成員(Eat方法、Shout方法)來表示這些動物的共同特征,而當(dāng)我們關(guān)注貓時,貓來實現(xiàn)這兩個成員(吃魚、喵喵叫);當(dāng)我們關(guān)注狗時,狗來實現(xiàn)這兩個成員(吃肉和汪汪叫)。

1.什么是多態(tài)?

上述例子就是一個典型的多態(tài),就是父類的一些成員,子類繼承后去重寫從而實現(xiàn)不同的功能。

多態(tài):同一操作作用于不同的對象,可以有不同的解釋,產(chǎn)生不同的執(zhí)行結(jié)果。這就是多態(tài),這種特性稱為多態(tài)性。

2.多態(tài)的分類

多態(tài)性分為兩種,一種是編譯時的多態(tài)性,一種是運(yùn)行時的多態(tài)性。

編譯時的多態(tài)性:編譯時的多態(tài)性是通過重載來實現(xiàn)的。對于非虛的成員來說,系統(tǒng)在編譯時,根據(jù)傳遞的參數(shù)、返回的類型等信息決定實現(xiàn)何種操作。

運(yùn)行時的多態(tài)性:運(yùn)行時的多態(tài)性就是指直到系統(tǒng)運(yùn)行時,才根據(jù)實際情況決定實現(xiàn)何種操作。C#中運(yùn)行時的多態(tài)性是通過覆寫虛成員實現(xiàn)。?

3.多態(tài)的實現(xiàn)

??我們知道多態(tài)有兩種,一種是編譯時通過重載實現(xiàn),另一種是運(yùn)行時,通過重寫或叫覆寫來實現(xiàn),那么如何實現(xiàn)他們?

3.1編譯時多態(tài):重載(overload

重載(overload):重載指的是同一個類中有兩個或多個名字相同但是參數(shù)不同的方法,(:返回值不能區(qū)別函數(shù)是否重載),重載沒有關(guān)鍵字。

注意:

A.從重載的定義來看,重載是一種編譯時多態(tài)

B.重載不需要事先定義可重載的方法,即沒有關(guān)鍵字

C.重載只是針對一個類內(nèi)部的幾個參數(shù)不同,名稱相同的方法。

我們還在本節(jié)開篇那幾只陶冶情操的動物來示例說明,代碼如下:

1 /// <summary> 2 /// 狗(多態(tài):重載事例) 3 /// </summary> 4 class Dog 5 { 6 /// <summary> 7 /// 8 /// </summary> 9 public void Shout() 10 { 11 Console.WriteLine("汪!"); 12 } 13 14 /// <summary> 15 /// 叫(重載方法) 16 /// </summary> 17 public void ShoutCount(int count) 18 { 19 int i = 0; 20 string shout = ""; 21 do 22 { 23 shout += "汪!"; 24 i++; 25 } while (i <= count); 26 Console.WriteLine(shout); 27 } 28 } //調(diào)用 Dog dog = new Dog(); dog.Shout(); dog.ShoutCount(5);

3.2運(yùn)行時多態(tài):重寫

重寫有兩種,一種是override修飾符,另一種使用new修飾符,下面會舉例說明兩種重寫的使用方法和異同。

重寫(override:也稱過載,重寫是指子類對父類中虛函數(shù)或抽象函數(shù)的“覆蓋”(這也就是有些書將過載翻譯為覆蓋的原因),但是這種“覆蓋”和用new關(guān)鍵字來覆蓋是有區(qū)別的。

下面以本節(jié)開題前例子,實現(xiàn)重寫,代碼如下:

?

1 /// <summary> 2 /// 動物類(父類) 3 /// </summary> 4 class Animal 5 { 6 /// <summary> 7 /// 名字 8 /// 說明:類和子類可訪問 9 /// </summary> 10 protected string name; 11 12 13 /// <summary> 14 /// 構(gòu)造函數(shù) 15 /// </summary> 16 /// <param name="name"></param> 17 public Animal(string name) 18 { 19 this.name=name; 20 } 21 22 /// <summary> 23 /// 名字(虛屬性) 24 /// </summary> 25 public virtual string MyName 26 { 27 get { return this.name; } 28 29 } 30 31 /// <summary> 32 /// 吃(虛方法) 33 /// </summary> 34 public virtual void Eat() 35 { 36 Console.WriteLine("我會吃!"); 37 } 38 39 /// <summary> 40 /// 叫(虛方法) 41 /// </summary> 42 public virtual void Shout() 43 { 44 Console.WriteLine("我會叫!"); 45 } 46 } 47 48 /// <summary> 49 /// 狗(子類) 50 /// </summary> 51 class Dog:Animal 52 { 53 string myName; 54 public Dog(string name): base(name) 55 { 56 myName = name; 57 } 58 59 /// <summary> 60 /// 名字(重寫父類屬性) 61 /// </summary> 62 public override string MyName 63 { 64 get { return "我是:狗狗,我叫:"+this.name; } 65 66 } 67 68 69 /// <summary> 70 /// 吃(重寫父類虛方法) 71 /// </summary> 72 public override void Eat() 73 { 74 Console.WriteLine("我喜歡吃肉!"); 75 } 76 77 /// <summary> 78 /// 叫(重寫父類方法) 79 /// </summary> 80 public override void Shout() 81 { 82 Console.WriteLine("汪!汪!汪!"); 83 } 84 } 85 /// <summary> 86 /// 貓(子類) 87 /// </summary> 88 class Cat : Animal 89 { 90 string myName; 91 public Cat(string name) 92 : base(name) 93 { 94 myName = name; 95 } 96 /// <summary> 97 /// 名字(重寫父類屬性) 98 /// </summary> 99 public override string MyName 100 { 101 get { return "我是:貓咪,我叫:" + this.name; } 102 103 } 104 105 /// <summary> 106 /// 吃(重寫父類虛方法) 107 /// </summary> 108 public override void Eat() 109 { 110 Console.WriteLine("我喜歡吃魚!"); 111 } 112 113 /// <summary> 114 /// 叫(重寫父類方法) 115 /// </summary> 116 public override void Shout() 117 { 118 Console.WriteLine("喵!喵!喵!"); 119 } 120 } 121 122 /// <summary> 123 /// 羊(子類) 124 /// </summary> 125 class Sheep : Animal 126 { 127 string myName; 128 public Sheep(string name) 129 : base(name) 130 { 131 myName = name; 132 } 133 /// <summary> 134 /// 名字(重寫父類屬性) 135 /// </summary> 136 public override string MyName 137 { 138 get { return "我是:羊羊,我叫:" + this.name; } 139 140 } 141 142 /// <summary> 143 /// 吃(重寫父類虛方法) 144 /// </summary> 145 public override void Eat() 146 { 147 Console.WriteLine("我喜歡吃草!"); 148 } 149 150 /// <summary> 151 /// 叫(重寫父類方法) 152 /// </summary> 153 public override void Shout() 154 { 155 Console.WriteLine("咩!咩!咩!"); 156 } 157 }

?

//調(diào)用方法 Animal dog = new Dog("旺財"); string myName=dog.MyName; Console.WriteLine(myName); dog.Eat(); dog.Shout(); //運(yùn)行結(jié)果如下: 我是:狗狗,我叫:旺財 我喜歡吃肉! 汪!汪!汪! //調(diào)用方法 Animal sheep = new Sheep("美羊羊"); string myName = sheep.MyName; Console.WriteLine(myName); sheep.Eat(); sheep.Shout(); //運(yùn)行結(jié)果如下: 我是:羊羊,我叫:美羊羊 我喜歡吃草! 咩!咩!咩!

重寫(new)

new:覆蓋指的是不同類中(基類或派生類)有兩個或多個返回類型、方法名、參數(shù)都相同,但是方法體不同的方法。但是這種覆蓋是一種表面上的覆蓋,所以也叫隱藏,被覆蓋的父類方法是可以調(diào)用得到的。

下面用實例說明,代碼如下:

?

1 /// <summary> 2 /// 動物類(父類) 3 /// </summary> 4 class Animal 5 { 6 /// <summary> 7 /// 名字 8 /// 說明:類和子類可訪問 9 /// </summary> 10 protected string name; 11 12 13 /// <summary> 14 /// 構(gòu)造函數(shù) 15 /// </summary> 16 /// <param name="name"></param> 17 public Animal(string name) 18 { 19 this.name=name; 20 } 21 22 /// <summary> 23 /// 名字(虛屬性) 24 /// </summary> 25 public virtual string MyName 26 { 27 get { return this.name; } 28 29 } 30 31 /// <summary> 32 /// 吃(虛方法) 33 /// </summary> 34 public virtual void Eat() 35 { 36 Console.WriteLine("我會吃!"); 37 } 38 39 /// <summary> 40 /// 叫(虛方法) 41 /// </summary> 42 public virtual void Shout() 43 { 44 Console.WriteLine("我會叫!"); 45 } 46 } 47 48 /// <summary> 49 /// 狗(子類) 50 /// </summary> 51 class Dog:Animal 52 { 53 string myName; 54 public Dog(string name): base(name) 55 { 56 myName = name; 57 } 58 /// <summary> 59 /// 名字(重寫父類屬性) 60 /// </summary> 61 public override string MyName 62 { 63 get { return "我是:狗狗,我叫:"+this.name; } 64 } 65 66 /// <summary> 67 /// 吃(重寫父類虛方法) 68 /// </summary> 69 new public void Eat() 70 { 71 Console.WriteLine("我喜歡吃肉!"); 72 } 73 74 /// <summary> 75 /// 叫(重寫父類方法) 76 /// </summary> 77 public new void Shout() 78 { 79 Console.WriteLine("汪!汪!汪!"); 80 } 81 }

?

//調(diào)用方法 Animal dog = new Dog("旺財"); string myName=dog.MyName; Console.WriteLine(myName); dog.Eat(); dog.Shout(); //執(zhí)行結(jié)果如下: 我是:狗狗,我叫:旺財 我會吃! 我會叫!

如下改一下調(diào)用方法:

//調(diào)用方法 Dog dog = new Dog("旺財"); string myName=dog.MyName; Console.WriteLine(myName); dog.Eat(); dog.Shout(); //執(zhí)行結(jié)果如下: 我是:狗狗,我叫:旺財! 我愛吃肉! 汪!汪!汪!

?

可以看出,當(dāng)派生類Dog的Eat()方法使用new修飾時,Dog的對象轉(zhuǎn)換為Animal對象后,調(diào)用的是Animal類中的Eat()方法。其實可以理解為,使用new關(guān)鍵字后,使得Dog中的Eat()方法和Animal中的Eat()方法成為毫不相關(guān)的兩個方法,只是它們的名字碰巧相同而已。所以, Animal類中的Eat()方法不管用還是不用virtual修飾,也不管訪問權(quán)限如何,或者是沒有,都不會對Dog的Eat()方法產(chǎn)生什么影響(只是因為使用了new關(guān)鍵字,如果Dog類沒用從Animal類繼承Eat()方法,編譯器會輸出警告)。?

我想這是設(shè)計者有意這么設(shè)計的,因為有時候我們就是要達(dá)到這種效果。嚴(yán)格的說,不能說通過使用new來實現(xiàn)多態(tài),只能說在某些特定的時候碰巧實現(xiàn)了多態(tài)的效果。

?

3.3?要點(diǎn):

a.多態(tài)是面向?qū)ο蟮闹匾匦灾?#xff0c;指同一操作作用于不同的對象,可以有不同的解釋,產(chǎn)生不同的執(zhí)行結(jié)果。

b.多態(tài)分為兩種:一種是編譯時多態(tài),使用重載實現(xiàn);另一種是運(yùn)行時多態(tài),使用重寫實現(xiàn);

c.重寫有兩種,一種使用override關(guān)鍵詞,另一種使用new關(guān)鍵詞

d.new重寫實際上是對父類方法的隱藏,被覆蓋的父類方法可以調(diào)用得到。因此new可以重寫(或說是隱藏)的父類方法不一定要定義為虛方法或抽象方法。只是如果父類方法是虛方法或抽象方法時會覆蓋父類方法,如果不是,則隱藏。

e.重載和覆蓋的發(fā)生條件:
重載,必然發(fā)生在一個類中,函數(shù)名相同,參數(shù)類型或者順序不同構(gòu)成重載,與返回類型無關(guān)
重寫,必然發(fā)生在基類和派生類中,其類函數(shù)用virtual修飾,派生類用override修飾
覆蓋,在子類中寫一個和基類一樣名字(參數(shù)不同也算)的非虛函數(shù),會讓基類中的函數(shù)被隱藏,編譯后會提示要求使用New關(guān)鍵字?new?修飾?

隱藏,在子類中可以通過new?隱藏父類的方法

f.new覆蓋與重寫、重載的區(qū)別:

當(dāng)子類與父類的參數(shù)不同時

當(dāng)基類函數(shù)不是虛函數(shù)時,基類函數(shù)將被隱藏。(因為子類和基類不在同一范圍內(nèi),所以不是重載)

當(dāng)基類函數(shù)是虛函數(shù)時,基類函數(shù)將被隱藏。(因為子類和基類不在同一范圍內(nèi),所以不是重載;因為參數(shù)不同,所以不是重寫)

當(dāng)子類與父類的參數(shù)相同時

當(dāng)基類函數(shù)不是虛函數(shù)時,基類函數(shù)將被隱藏。(因為子類和基類不在同一范圍內(nèi),所以不是重載,因為基類不是虛函數(shù),所以是隱藏不是重寫)

當(dāng)基類函數(shù)是虛函數(shù)時,基類函數(shù)將被覆蓋。(因為子類和基類不在同一范圍內(nèi),所以不是重載)

==============================================================================================

返回目錄

?<如果對你有幫助,記得點(diǎn)一下推薦哦,有不明白的地方或?qū)懙牟粚Φ牡胤?#xff0c;請多交流>

==============================================================================================?

轉(zhuǎn)載于:https://www.cnblogs.com/yubinfeng/p/4557160.html

總結(jié)

以上是生活随笔為你收集整理的[.net 面向对象编程基础] (13) 面向对象三大特性——多态的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。