【问题标题】: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?

【问题讨论】:

    标签: c# .net polymorphism overloading


    【解决方案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() 这是多态应该工作的方式。

        【讨论】:

          猜你喜欢
          • 2011-06-25
          • 2017-06-06
          • 1970-01-01
          • 2010-11-14
          • 2011-10-15
          • 2015-09-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多