C#中多態景象和多態的完成辦法。本站提示廣大學習愛好者:(C#中多態景象和多態的完成辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是C#中多態景象和多態的完成辦法正文
本文實例講述了C#中多態景象和多態的完成辦法。分享給年夜家供年夜家參考。詳細剖析以下:
面向對象的特點封裝、繼續和多態。Polymorphism(多態性)起源於希臘單詞,指“多種形狀”。多態性的一個主要特點是辦法的挪用是在運轉時肯定而不是編譯時。在.NET頂用於完成多態性的症結詞有virtual、override、abstract、interface。
1、virtual完成多態
shape類是通用的基類,draw是一個虛辦法,每一個派生類都可以有本身的override版本,在運轉時可以用shape類的變量靜態的挪用draw辦法。
public class Shape { public virtual void Draw() { Console.WriteLine("base class drawing"); } } public class Rectangle :Shape { public override void Draw() { Console.WriteLine("Drawing a Rectangle"); } } public class Square :Rectangle { public override void Draw() { Console.WriteLine("Drawing a Square"); base.Draw(); } } class Program { static void Main(string[]args) { System.Collections.Generic.List<Shape> shapes =new List<Shape>(); shapes.Add(new Rectangle()); shapes.Add(new Square()); foreach(Shape s in shapes) { s.Draw(); } Console.ReadKey(); /*運轉成果 Drawing a Rectangle Drawing a Square Drawing a Rectangle */ } }
辦法、屬性、事宜、索引器都可以被virtual潤飾,然則字段弗成以。派生類必需用override表現類成員介入虛挪用。假設把Square中的draw辦法調換為用new 潤飾,則表現draw辦法不介入虛挪用,並且是一個新的辦法,只是名字和基類辦法重名。
public new void Draw() { Console.WriteLine("Drawing a Square"); base.Draw(); }
這個辦法在Main辦法中的foreach中將不會被挪用,它不是虛辦法了。用new潤飾符後的法式運轉成果,
/*運轉成果 Drawing a Rectangle Drawing a Rectangle */
假設說虛辦法在rectangle擴大後,不願望square擴大了,可以在辦法前加上sealed潤飾符,
以下
public class Rectangle :Shape { public sealed override voidDraw() { Console.WriteLine("Drawing a Rectangle"); } }
當派生類重寫某個虛擬成員時,即便該派生類的實例被看成基類的實例拜訪或許把派生類實例賦給父類變量停止拜訪,然則照樣會挪用派生類重寫後的成員,可以把代碼改成以下情勢,
static void Main(string[] args) { System.Collections.Generic.List<Shape>shapes =new List<Shape>(); shapes.Add((Shape)new Rectangle()); shapes.Add((Shape)new Square()); foreach(Shape s inshapes) { s.Draw(); } Console.ReadKey(); /*運轉成果 Drawing a Rectangle Drawing a Square Drawing a Rectangle */ }
2、abstract完成多態
被abstract潤飾的辦法,默許是虛擬的,然則不克不及湧現virtual症結詞潤飾。被abstract潤飾的類可以有已完成的成員,可以有本身的字段,可以有非abstract 潤飾的辦法,然則不克不及實例化由於籠統的器械是沒有實例對應的。好比,有人讓我們畫個圖形(籠統)是畫不出來的,然則讓畫個矩形(詳細)是可以畫出來的。上面是用abstract完成的多態版本,
public abstract classShape { public abstract void Draw(); } public class Rectangle :Shape { public override void Draw() { Console.WriteLine("Drawing a Rectangle"); } } public class Square :Rectangle { public override void Draw() { Console.WriteLine("Drawing a Square"); base.Draw(); } } class Program { static void Main(string[]args) { System.Collections.Generic.List<Shape>shapes =new List<Shape>(); shapes.Add(new Rectangle()); shapes.Add(new Square()); foreach(Shape s in shapes) { s.Draw(); } Console.ReadKey(); } }
被abstract潤飾的辦法,在派生類中異樣用override症結詞停止擴大。異樣可以用症結詞sealed阻攔派生類停止擴大。
interface完成多態
接口可由辦法、屬性、事宜、索引器或這四種成員類型的任何組合組成。接口不克不及包括字段。接口成員默許是公共的,籠統的,虛擬的。若要完成接口成員,類中的對應成員必需是公共的、非靜態的,而且與接口成員具有雷同的稱號和簽名。上面是interface完成的多態版本
public interface IShape { void Draw(); } public class Rectangle :IShape { public void Draw() { Console.WriteLine("Drawing a Rectangle"); } } public class Square: IShape { public void Draw() { Console.WriteLine("Drawing a Square"); } } class Program { static void Main(string[]args) { System.Collections.Generic.List<IShape>shapes =new List<IShape>(); shapes.Add(new Rectangle()); shapes.Add(new Square()); foreach(IShape s inshapes) { s.Draw(); } Console.ReadLine(); } }
籠統類與接口
類可以完成無窮個接口,但僅能從一個籠統(或任何其他類型)類繼續。從籠統類派生的類仍可完成接口。msdn的在接口和籠統類的選擇方面給的一些建議,
假如估計要創立組件的多個版本,則創立籠統類。籠統類供給簡略易行的辦法來掌握組件版本。經由過程更新基類,一切繼續類都隨更改主動更新。另外一方面,接口一旦創立就不克不及更改。假如須要接口的新版本,必需創立一個全新的接口。
假如創立的功效將在年夜規模的全異對象間應用,則應用接口。籠統類應重要用於關系親密的對象,而接口最合適為不相干的類供給通用功效。
假如要設計小而簡潔的功效塊,則應用接口。假如要設計年夜的功效單位,則應用籠統類。
假如要在組件的一切完成間供給通用的已完成功效,則應用籠統類。籠統類許可部門完成類,而接口不包括任何成員的完成。
一個綜合性的實例
public interface IShape { void Draw(); } public class Shape:IShape { void IShape.Draw() { Console.WriteLine("Shape IShape.Draw()"); } public virtual void Draw() { Console.WriteLine("Shape virtual Draw()"); } } public class Rectangle :Shape,IShape { void IShape.Draw() { Console.WriteLine("Rectangle IShape.Draw()"); } public newvirtual void Draw() { Console.WriteLine("Rectangle virtual Draw()"); } } public class Square :Rectangle { public override void Draw() { Console.WriteLine("Square override Draw()"); } } class Program { static void Main(string[]args) { Square squre = new Square(); Rectangle rect = squre; Shape shape = squre; IShape ishape = squre; squre.Draw(); rect.Draw(); shape.Draw(); ishape.Draw(); Console.ReadLine(); } } /*運轉成果: Square override Draw()① Square override Draw()② Shape virtual Draw()③ Rectangle IShape.Draw()④ */
在這個法式裡,把派生類實例賦給父類變量或許接口。對成果①無需說明。成果②,由於Draw辦法是虛辦法,虛辦法的挪用規矩是挪用離實例變量比來的override版本辦法,Square類中的Draw辦法是離實例square比來的辦法,即便是把Square類型的實例賦值給Rectangle類型的變量去拜訪,依然挪用的是Square類重寫的辦法。關於成果③,也是虛辦法挪用,在子類Rectangle中的draw辦法用new潤飾,這就注解shape類中的virtual到其中斷,前面Square中的override版是針對Rectangle中的Draw辦法,此時,離square實例比來的完成就是Shape類中的Draw 辦法,由於Shape類中的Draw辦法沒有override的版本只能挪用自己的virtual版了。成果④,由於Rectangle從新聲明完成接口IShape,接口挪用異樣相符虛辦法挪用規矩,挪用離它比來的完成,Rectangle中的完成比Shape中的完成離實例square更近。Rectangle中的IShape.Draw()辦法是顯式接口辦法完成,關於它不克不及有任何的拜訪潤飾符,只能經由過程接口變量拜訪它,同時也不克不及用virtual或許override停止潤飾,也不克不及被派生類型挪用。只能用IShape變量停止拜訪。假如類型中有顯式接口的完成,並且用的是接口變量,默許挪用顯式接口的完成辦法。
override和辦法選擇
public class Base { public virtual void Write(int num) { Console.WriteLine("int:" + num.ToString()); } } public class Derived :Base { public override void Write(int num) { Console.WriteLine("derived:" + num.ToString()); } public void Write(double num) { Console.WriteLine("derived double:" + num.ToString()); } }
願望本文所述對年夜家的C#法式設計有所贊助。