【问题标题】:invoke a new method of a sub class from base class从基类调用子类的新方法
【发布时间】:2011-01-22 16:06:53
【问题描述】:

我有一些这样的课程

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            A a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public virtual void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public override void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}

它工作正常,打印“METHOD FROM C”

但是

如果我有这样的情况

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            A a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public new void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}

它打印“来自 A 的方法”。如何在不采用强制转换或更改方法声明的情况下获得与第一个示例相同的行为?

【问题讨论】:

    标签: c# methods new-operator invoke base-class


    【解决方案1】:

    你不能 - 这种行为差异是使用虚拟/覆盖的全部意义。

    当你用“new”声明一个方法时,你是在说“我知道我在隐藏一个具有相同签名的方法,而不是覆盖它;我不想要多态行为。”

    同样,当您声明一个方法而不指定“虚拟”时,您是在说“我不希望子类能够覆盖此方法。”

    为什么要这样做?您实际上是否只是试图覆盖尚未声明为虚拟的方法?如果是这样,就没有办法绕过它——而且有充分的理由。如果作者在设计类时没有考虑到多态性,如果您能够覆盖该方法,它很容易崩溃。

    当然,如果你将变量声明为子类的类型,像这样:

    C c = new C();
    c.method();
    

    那么调用新声明的方法。

    【讨论】:

      【解决方案2】:

      就像乔恩说的那样,避免它。但是

      static void Main(string[] args)
          {
              A a = new C();
      
              (a as C).method();
      
              Console.ReadLine();
          }
      

      【讨论】:

        【解决方案3】:

        您可以使用动态关键字调用此方法。

        namespace ConsoleApplication1
        {
            class Program
            {
                static void Main(string[] args)
                {
                    dynamic a = new C();
        
                    a.method();
                    Console.ReadLine();
                }
            }
        
            public class A
            {
                public void method()
                {
                    Console.WriteLine("METHOD FROM A");
                }
            }
        
            public class B : A { }
        
            public class C : B
            {
                public new void method()
                {
                    Console.WriteLine("METHOD FROM C");
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2018-10-15
          • 2011-01-05
          • 2016-10-05
          • 1970-01-01
          • 2017-12-13
          • 2010-12-05
          • 1970-01-01
          • 2012-06-28
          • 2012-08-04
          相关资源
          最近更新 更多