转载自:MSDN
相似文章:点击翻开链接
Polymorphism(多态性)是一个希腊词,指“多种外形”,多态性具有两个判然不同的方面:
发作此状况时,该对象的声明范例不再与运行时范例雷同。
在运行时,客户端代码挪用该要领,CLR 查找对象的运行时范例,并挪用虚要领的重写要领。 因而,你可以在源代码中挪用基类的要领,但实行该要领的派生类版本。
派生类(子类)与基类(父类)之间强迫转换不会丧失信息。
namespace PolymorphismTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { ParentClass parent = new ParentClass(); SubClass sub = new SubClass(); parent = ((ParentClass)sub); //子类 父类 实例之间往返转换不会丧失信息 SubClass subNew = (SubClass)parent; } } public class SubClass : ParentClass { public new string name = "SubClass"; public int age = 20; } public class ParentClass { string name = "ParentClass"; } }
实行到
SubClass subNew = (SubClass)parent
详细效果以下图:
比方,假定你有一个画图应用程序,许可用户在画图图面上建立种种外形。 你在编译时不知道用户将建立哪些特定范例的外形。 但应用程序必需跟踪建立的一切范例的外形,而且必需更新这些外形以响应用户鼠标操纵。 你可以运用多态性经由过程两个基础步骤处理这一题目:
建立一个类条理构造,个中每一个特定外形类均派生自一个大众基类。
运用虚要领经由过程对基类要领的单个挪用来挪用任何派生类上的响应要领。
为 Shape 类供应一个名为 Draw 的虚要领,并在每一个派生类中重写该要领以绘制该类示意的特定外形。建立一个 List<Shape> 对象,并向该对象增加 Circle、Triangle 和 Rectangle。 若要更新画图图面,请运用 foreach 轮回对该列表举行轮回接见,并对个中的每一个 Shape 对象挪用 Draw 要领。 虽然列表中的每一个对象都具有声明范例 Shape,但挪用的将是运行时范例(该要领在每一个派生类中的重写版本)。
C#
public class Shape { // A few example members public int X { get; private set; } public int Y { get; private set; } public int Height { get; set; } public int Width { get; set; } // Virtual method public virtual void Draw() { Console.WriteLine("Performing base class drawing tasks"); } }class Circle : Shape { public override void Draw() { // Code to draw a circle... Console.WriteLine("Drawing a circle"); base.Draw(); } }class Rectangle : Shape { public override void Draw() { // Code to draw a rectangle... Console.WriteLine("Drawing a rectangle"); base.Draw(); } }class Triangle : Shape { public override void Draw() { // Code to draw a triangle... Console.WriteLine("Drawing a triangle"); base.Draw(); } }class Program { static void Main(string[] args) { // Polymorphism at work #1: a Rectangle, Triangle and Circle // can all be used whereever a Shape is expected. No cast is // required because an implicit conversion exists from a derived // class to its base class. System.Collections.Generic.List<Shape> shapes = new System.Collections.Generic.List<Shape>(); shapes.Add(new Rectangle()); shapes.Add(new Triangle()); shapes.Add(new Circle()); // Polymorphism at work #2: the virtual method Draw is // invoked on each of the derived classes, not the base class. foreach (Shape s in shapes) { s.Draw(); } // Keep the console open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } }/* Output: Drawing a rectangle Performing base class drawing tasks Drawing a triangle Performing base class drawing tasks Drawing a circle Performing base class drawing tasks */
在 C# 中,每一个范例都是多态的,由于包含用户定义范例在内的一切范例都继续自 Object。
关注对象准绳:挪用子类照样父类的要领,取决于建立的对象是子类对象照样父类对象
多态性概述
虚成员
派生类的设想器可以挑选是不是
重写基类中的假造成员。
继续最接近的基类要领而不重写它
定义隐蔽基类完成的成员的新非虚完成
派生成员必需运用 override 关键字显式指导该要领将介入虚挪用。 以下代码供应了一个示例:
C#
public class BaseClass { public virtual void DoWork() { } public virtual int WorkProperty { get { return 0; } } }public class DerivedClass : BaseClass { public override void DoWork() { } public override int WorkProperty { get { return 0; } } }
当派生类重写某个假造成员时,纵然该派生类的实例被看成基类的实例接见,也会挪用该成员。 以下代码供应了一个示例:
C#
DerivedClass B = new DerivedClass(); B.DoWork(); // Calls the new method.BaseClass A = (BaseClass)B; A.DoWork(); // Also calls the new method.
有关详细信息,请参阅运用 Override 和 New 关键字举行版本掌握(C# 编程指南)。 接口供应另一种体式格局来定义将完成留给派生类的要领或要领集。 有关详细信息,请参阅接口(C# 编程指南)。
运用新成员隐蔽基类成员
new 关键字安排在要替代的类成员的返回范例之前。 以下代码供应了一个示例:
C#
public class BaseClass { public void DoWork() { WorkField++; } public int WorkField; public int WorkProperty { get { return 0; } } }public class DerivedClass : BaseClass { public new void DoWork() { WorkField++; } public new int WorkField; public new int WorkProperty { get { return 0; } } }
比方:
C#
DerivedClass B = new DerivedClass(); B.DoWork(); // Calls the new method.BaseClass A = (BaseClass)B; A.DoWork(); // Calls the old method.
阻挠派生类重写假造成员
假如类 A 声清楚明了一个假造成员,类 B 从 A 派生,类 C 从类 B 派生,则类 C 继续该假造成员,而且可以挑选重写它,而不论类 B 是不是为该成员声清楚明了重写。 以下代码供应了一个示例:
C#
public class A { public virtual void DoWork() { } }public class B : A { public override void DoWork() { } }
这需要在类成员声明中的 override 关键字前面安排 sealed 关键字。 以下代码供应了一个示例:
C#
public class C : B { public sealed override void DoWork() { } }
纵然它们转换为范例 B 或范例 A,它关于 C 的实例仍然是假造的。 经由过程运用 new 关键字,密封的要领可以由派生类替代,以下面的示例所示:
C#
public class D : C { public new void DoWork() { } }
假如运用范例为 C、B 或 A 的变量接见 D 的实例,对 DoWork 的挪用将遵照假造继续的划定规矩,即把这些挪用传送到类 C 的 DoWork 完成。
从派生类接见基类假造成员
以下代码供应了一个示例:
C#
public class Base { public virtual void DoWork() {/*...*/ } }public class Derived : Base { public override void DoWork() { //Perform Derived's work here //... // Call DoWork on base class base.DoWork(); } }
有关详细信息,请参阅 base。
申明 |
---|
许可基类行动发作使得派生类可以集中精力完成特定于派生类的行动。 未挪用基类完成时,由派生类担任使它们的行动与基类的行动兼容。 |
以上就是C# 多态性的内容,更多相关内容请关注ki4网(www.ki4.cn)!