方法重载和多态性

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&lt;A&gt;。所以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);
    

这种方法的优点是它允许您有效地实现多态性(每种类型确保通过在内部传递强类型 thisRender 来调用正确的重载),同时保留不属于您的逻辑类型自己(例如,视觉呈现逻辑)出来。

【讨论】:

【参考方案4】:

使 A B C 派生自一个基(抽象)类,在该类中定义一个方法 Render 并在每个 A B C 中正确覆盖。而不是调用Render(a) 然后调用a.Render() 这是多态应该工作的方式。

【讨论】:

以上是关于方法重载和多态性的主要内容,如果未能解决你的问题,请参考以下文章

封装继承和多态,重写重载等基础复习

请简述重载和重写的区别

重载和重写有啥区别

什么是java方法重载

方法的重载和重写

多态性和方法重载