方法重载和多态性
Posted
技术标签:
【中文标题】方法重载和多态性【英文标题】:Method overloading and polymorphism 【发布时间】:2011-06-22 17:48:24 【问题描述】:class Program
static void Main(string[] args)
List<A> myList = new List<A> new A(), new B(), new C();
foreach (var a in myList)
Render(a);
Console.ReadKey();
private static void Render(A o)
Console.Write("A");
private static void Render(B b)
Console.Write("B");
private static void Render(C c)
Console.Write("C");
class A
class B : A
class C : A
输出为:AAA
是否有可能以某种方式使用方法重载,以便输出为:ABC?
【问题讨论】:
【参考方案1】:如果您使用 C# 4,则可以使用动态类型:
foreach (dynamic a in myList)
Render(a);
在静态类型中,重载决议是在编译时执行的,而不是在执行时。
要在决策时选择实现,您要么必须使用覆盖而不是重载,要么使用上述动态类型。
【讨论】:
即使重载解析是在编译时完成的,为什么选择“A a”而不是“B b”和“C c”。 @Sandeep:因为Main
中的a
变量的编译时类型只有A,因为列表是List<A>
。所以Render(a)
只能选择Render(A a)
。【参考方案2】:
以下内容应该可以解决问题,我们可以控制使用该类型中的类型时的行为:
class A
public virtual void Render()
Console.WriteLine("A");
class B : A
public override void Render()
Console.WriteLine("B");
class C : A
public override void Render()
Console.WriteLine("C");
static void Main(string[] args)
var myList = new List<A> new A(), new B(), new C() ;
foreach (var a in myList)
a.Render();
Console.ReadKey();
如果你想让一个类型定义的行为与其父类型的行为相加,那么在执行你自己的逻辑之后调用基类中实现的方法,例如:
class B : A
public override void Render()
Console.WriteLine("B");
base.Render();
【讨论】:
【参考方案3】:实现此目的的另一种方法是使用visitor pattern:它允许您使用双向方法调用系统实现类似的多态性:
interface IRenderable
AcceptForRender(Program renderer);
class Program
static void Main(string[] args)
var p = new Program();
var myList = new List<IRenderable> new A(), new B(), new C();
foreach (var a in myList)
a.AcceptForRender(p);
Console.ReadKey();
public void Render(A o)
Console.Write("A");
public void Render(B b)
Console.Write("B");
public void Render(C c)
Console.Write("C");
class A : IRenderable
public void AcceptForRender(Program renderer)
renderer.Render(this);
class B : IRenderable
public void AcceptForRender(Program renderer)
renderer.Render(this);
class C : IRenderable
public void AcceptForRender(Program renderer)
renderer.Render(this);
这种方法的优点是它允许您有效地实现多态性(每种类型确保通过在内部传递强类型 this
到 Render
来调用正确的重载),同时保留不属于您的逻辑类型自己(例如,视觉呈现逻辑)出来。
【讨论】:
【参考方案4】:使 A B C 派生自一个基(抽象)类,在该类中定义一个方法 Render 并在每个 A B C 中正确覆盖。而不是调用Render(a)
然后调用a.Render()
这是多态应该工作的方式。
【讨论】:
以上是关于方法重载和多态性的主要内容,如果未能解决你的问题,请参考以下文章