【问题标题】:Method hiding plus overriding calling decision方法隐藏和覆盖调用决策
【发布时间】:2016-05-08 09:06:00
【问题描述】:

在基于类型引用对象的方法覆盖的情况下,将决定保留方法调用。 方法隐藏的情况下,将根据对象方法调用的类型来决定。

谁能解释一下覆盖+隐藏中的方法调用决策。

public class Base
    {
        public virtual void DoIt()
        {
        }
    }

    public class Derived : Base
    {
        public  override void DoIt()
        {
        }
    }

    public class Derived1 : Derived
    {
        public new void DoIt()
        {
        }
    }
    class Program
    {
        static void Main(string[] args)
        {

            Base b = new Derived();
            Derived d = new Derived();
      #1    b.DoIt();                      // Calls Derived.DoIt
      #2    d.DoIt();                     // Calls Derived.DoIt
            b = new Derived1();
            d = new Derived1();
      #3    b.DoIt();                      // Calls Derived.DoIt
      #4    d.DoIt();
}
}

#1 和 #2 调用 Derived.DoIt 因为运行时多态性。

#4 称为 Derived.DoIt,因为 d 是 Derived 类型(方法隐藏)。

但是为什么 #3 调用 Derived.DoIt。

在c#中覆盖加隐藏时的调用顺序是什么。

提前致谢

【问题讨论】:

  • 你可以这样想:Derived1 有两个DoIt 方法——一个继承自Base 类,另一个在Derived1 本身中声明。当您在 Base 或 Derived 类型的实例上调用 DoIt 时 - 他们只知道一种 DoIt 方法而对另一种方法一无所知,因此会调用此方法。

标签: c# overriding method-hiding


【解决方案1】:

因为#3 是Base 类型的实例。这里,Base 的最后一个派生方法驻留在Derived 类中,因此它被调用了。

new/方法隐藏/阴影不同于方法覆盖,因为覆盖意味着您正在自定义基本方法,而new 意味着您只是为相同的方法名称提供不同的实现。

【讨论】:

    【解决方案2】:

    在方法覆盖中,在运行时决定调用哪个类型的方法,但是方法隐藏或隐藏是编译时的事情,编译器在编译时知道调用哪个类型的方法,当你使用new方法签名中派生类型中的关键字而不是覆盖,这意味着如果您使用基类的引用调用它将调用基类实现,如果您使用派生类引用它将调用派生类方法实现。

    派生类实现对基类隐藏。

    如果你这样写:

    b = new Derived1();
    b.DoIt() // (run-time) will call Dervied method implementation as Dervied has overridden 
            // so calling via base reference will call overridden implementation if any
           //otherwise base class implementation will get called
    
    Derived1 d1 = (Derived1)b;
    d1.DoIt(); // (compile time) will call Derived1 method implementation due to hiding in Derived1
    Derived d = (Derived)b;
    d.DoIt(); // (run-time) will call Derived method implementation due to override 
    

    【讨论】:

      【解决方案3】:

      #3 调用 Derived.DoIt() 因为该方法只是隐藏的,如果使用适当的强制转换,它仍然可以在外部调用。变量 b 的类型是 Base,因此您正在访问 Base 可用的方法。这是通过 Derived 覆盖的结果,因此您的结果是来自 Derived.DoIt 的结果。如果你有一个 Derived1 类型的变量并在那里调用 DoIt,那么 Derived1.DoIt 会被调用。

      public class Base
      {
          public virtual void DoIt()
          {
              Console.WriteLine("Base.DoIt was called!");
          }
      }
      
      public class Derived : Base
      {
          public override void DoIt()
          {
              Console.WriteLine("Derived.DoIt was called!");
          }
      }
      
      public class Derived1 : Derived
      {
          public new void DoIt()
          {
              Console.WriteLine("Derived1.DoIt was called!");
          }
      }
      class Program
      {
          static void Main(string[] args)
          {
      
              Base b = new Derived();
              Derived d = new Derived();
              Console.WriteLine("#1");
              b.DoIt();                      
              Console.WriteLine("#2");
              d.DoIt();                     
              b = new Derived1();
              d = new Derived1();
              Console.WriteLine("#3");
              b.DoIt();                    
              Console.WriteLine("#4");
              d.DoIt();
              Console.WriteLine("#5");
              Derived1 e = new Derived1();
              e.DoIt();
              Console.ReadKey();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2013-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-19
        • 2017-09-21
        • 2015-10-17
        相关资源
        最近更新 更多