Method overloading and polymorphism
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
{
}
The output is: AAA
Is it possible to somehow use method overloading, so that the output would be: ABC?
You can use dynamic typing if you're using C# 4:
foreach (dynamic a in myList)
{
Render(a);
}
Within static typing, overload resolution is performed at compile-time, not at execution time.
For the implementation to be chosen at decision time, you either have to use overriding instead of overloading, or use dynamic typing as above.
The following ought to do the trick, where we control the behaviour when working with a type within that type:
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();
}
And if you want the defined behaviour of a type to be additive to that of its parent, then call the method implemented in the base after executing your own logic, for example:
class B : A
{
public override void Render()
{
Console.WriteLine("B");
base.Render();
}
}
Another way to accomplish this is with the visitor pattern: it allows you to achieve something like polymorphism using a two-way method calling system:
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);
}
}
The advantage to this approach is that it allows you to effectively achieve polymorphism (each type ensures the correct overload is called by passing the strongly-typed this
to Render
internally) while keeping logic that does not belong in your types themselves (e.g., visual rendering logic) out.
Make A B C deriving from a base ( abstract ) class, define in that class a method Render and override properly in each A B C . Instead of calling Render(a)
then call a.Render()
this is the way polymorfism is supposed to work.
精彩评论