多態性html
首先理解一下什麼叫多態。同一操做做用於不一樣的對象,能夠有不一樣的解釋,產生不一樣的執行結果,這就是多態性。設計模式
多態性經過派生類覆寫基類中的虛函數型方法來實現。ide
多態性分爲兩種,一種是編譯時的多態性,一種是運行時的多態性。函數
編譯時的多態性:編譯時的多態性是經過重載來實現的。對於非虛的成員來講,系統在編譯時,根據傳遞的參數、返回的類型等信息決定實現何種操做。測試
運行時的多態性:運行時的多態性就是指直到系統運行時,才根據實際狀況決定實現何種操做。C#中運行時的多態性是經過覆寫虛成員實現。spa
下面咱們來分別說明一下多態中涉及到的四個概念:重載,覆寫,虛方法和抽象方法。設計
重載和覆寫的區別:htm
重載對象
類中定義的方法的不一樣版本blog
public int Calculate(int x, int y)
public double Calculate(double x, double y)
特色(兩必須一能夠)
方法名必須相同
參數列表必須不相同
返回值類型能夠不相同
覆寫
子類中爲知足本身的須要來重複定義某個方法的不一樣實現。
經過使用override關鍵字來實現覆寫。
只有虛方法和抽象方法才能被覆寫。
要求(三相同)
相同的方法名稱
相同的參數列表
相同的返回值類型
例:
public class Test
{
public int Calculate(int x, int y)
{
return x + y;
}
public double Calculate(double x, double y)
{
return x + y;
}
}
首先看這個類,咱們在同一個類中知足了重載的三個特色,方法名必須相同Calculate;參數列表必須不相同第一個方法的兩個參數類型爲int類型,第二個方法的兩個參數類型爲double類型;返回值類型能夠不相同一個返回值類型爲int,另外一個返回值類型爲double。
而後咱們在客戶程序中調用這兩個方法。
這時候咱們發現智能提示裏提示這個方法已經被重載過一次了。這樣咱們就能夠根據業務邏輯調用不一樣的方法來實現不一樣的業務。
客戶端測試程序:
Test t = new Test();
int x;
int y;
Console.WriteLine("Please input an integer.\n");
x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Please input another integer.\n");
y = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Test class Calculate method result.\n");
int result1 = t.Calculate(x,y);
Console.WriteLine("int x + int y = {0}\n",result1.ToString());
double a;
double b;
Console.WriteLine("Please input an double.\n");
a = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Please input another double.\n");
b = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Test class Calculate method result.\n");
double result2 = t.Calculate(a,b);
Console.WriteLine("double x + double y = {0}\n",result2.ToString());
Console.ReadLine();
執行結果爲:
下面來看一看覆寫,咱們將基類(父類)做一下修改
public class Test
{
public virtual int Calculate(int x, int y)
{
return x + y;
}
public virtual double Calculate(double x, double y)
{
return x + y;
}
}
派生類(子類)
public class TestOverride : Test
{
public override int Calculate(int x, int y)
{
return x * y;
}
public override double Calculate(double x, double y)
{
return x * y;
}
}
這是咱們會在客戶端的測試程序中發現,咱們既能夠訪問到覆寫後的方法也能訪問到覆寫前基類的方法,顯示被重載3次,其中兩次是被覆寫的
客戶端測試程序
TestOverride t = new TestOverride();
int x;
int y;
Console.WriteLine("Please input an integer.\n");
x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Please input another integer.\n");
y = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Test class Calculate method result.\n");
int result1 = t.Calculate(x,y);
Console.WriteLine("int x * int y = {0}\n",result1.ToString());
double a;
double b;
Console.WriteLine("Please input an double.\n");
a = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Please input another double.\n");
b = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Test class Calculate method result.\n");
double result2 = t.Calculate(a,b);
Console.WriteLine("double x * double y = {0}\n",result2.ToString());
Console.ReadLine();
執行結果爲:
這裏還有一個須要提的地方就是在子類若是須要訪問父類的方法可使用base關鍵字,例如:
public class TestOverride : Test
{
public override int Calculate(int x, int y)
{
return base.Calculate (x, y);
}
public override double Calculate(double x, double y)
{
return base.Calculate (x, y);
}
}
這樣咱們在客戶程序進行訪問繼承Test類TestOverride類的方法時返回的仍是加法運算的結果。
咱們來對重載和覆寫做一個比較
|
Override覆寫 |
Overload重載 |
位置 |
存在於繼承關係的類中 |
存在於同一類中 |
方法名 |
相同 |
相同 |
參數列表 |
相同 |
必須不一樣 |
返回值 |
相同 |
能夠不相同 |
最後再來介紹一下虛方法和抽象方法
虛方法
聲明使用virtual關鍵字。
調用虛方法,運行時將肯定調用對象是什麼類的實例,並調用適當的覆寫的方法。
虛方法能夠有實現體。
抽象方法
必須被派生類覆寫的方法。
能夠當作是沒有實現體的虛方法。
若是類中包含抽象方法,那麼類就必須定義爲抽象類,不管是否還包含其餘通常方法。
關於虛方法,上面咱們作了一些實驗,下面來看一個關於抽象方法的例子。
例:
public class TestOverride : Test
{
public abstract int Calculate(int x, int y);
public abstract double Calculate(double x, double y);
}
在編譯的時候會出現一個錯誤
要求抽象方法必須被報刊在抽象類中,咱們做以下修改
Public abstract class TestOverride : Test
{
public abstract int Calculate(int x, int y);
public abstract double Calculate(double x, double y);
}
這時知足了抽象方法的要求,便可編譯經過
一樣咱們還能夠對其進行覆寫,其實這裏的覆寫就是咱們所說的對於一個抽象的具體實現。如上面離子所示,咱們先用一個抽象類定義了一個測試類並在其中定義了這個類能夠作兩個整數或者實數的計算操做,至於具體作什麼樣的計算和怎麼計算並無定義,只是聲明我能作這些事,而後在它的子類(一個具體的類)中實現了他的定義,咱們要作的是乘法計算。咱們還能夠經過另外一個具體的類還定義咱們可能要作的不是乘法計算而是加法計算。代碼以下:
public class TestAdd : Test
{
public override int Calculate(int x, int y)
{
return x + y;
}
public override double Calculate(double x, double y)
{
return x + y;
}
}
這樣咱們就實現了用抽象類來定義操做,用具體的類還根據不一樣狀況實現不一樣的操做。關於這一點就引出了咱們設計模式中建立型模式中的工廠方法、建造者、抽象工廠方法等(這些是我暫時學到的模式),若是你們想了解這些知識能夠參考TerryLee的設計模式系列文章,很經典。
到此爲止咱們介紹了C#中多態性涉及的幾個概念,但願對你們的在之後代碼結構設計上能有所幫助:)
在這裏牢騷幾句,如今的項目中變化是一件很日常的事,咱們設計的軟件就是要適應這種常常的變化,將項目中的一些變化點封裝起來,在業務發生變化的時候咱們能很輕鬆的應對這種變化。一個軟件的一定會通過它生命週期中的各個部分並最後走向死亡,可是咱們能夠在設計中經過使軟件有能力來應對這些變化來使它的生存期長一些,會爲咱們帶來更多的價值(哈哈,這些其實就是設計模式所要達到的一些目的)。
但願你們能今後文中獲得一些收穫,謝謝:)