【问题标题】:Why does new "hide" the base class method?为什么新的“隐藏”基类方法?
【发布时间】:2018-01-29 12:01:53
【问题描述】:

我对术语有疑问。根据 MSDN:“override 修饰符扩展了基类方法,而 new 修饰符隐藏了它。” 但是,在以下示例中:

using System;

namespace ConsoleApplication2
{
    class BaseClass
    {
        public virtual void Method1()
        {
            Console.WriteLine("Base - Method1");
        }
    }

    class DerivedClass : BaseClass
    {
        public void Method1() // DerivedClass.Method1() hides inherited memeber BaseClass.Method1(). Use the new keyword if hiding was intended.
        {
            Console.WriteLine("Derived - Method1");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            BaseClass bd = new DerivedClass();
            bd.Method1();
            Console.ReadLine();

        }
    }
}

你会看到,如果你在DerivedClass中声明Method1()时使用new,bd.Method1()会按照基类的指示输出:“Base - Method1”。

...然而,如果您在 DerivedClass 中声明 Method1() 时使用 override,则 bd.Method1() 将按照派生类中的说明输出:“Derived - Method1”。

为什么每个来源(包括官方文档)都说 new 隐藏 base 类方法,而在这个例子中,base类方法是使用new时调用的方法吗?

我了解不同的行为(新行为与覆盖相比),但不了解术语。

【问题讨论】:

标签: c#


【解决方案1】:

方法隐藏基类中的方法是什么意思?

class BaseClass
{
    public virtual void Method1()
    {
        Console.WriteLine("Base - Method1");
    }
}

class DerivedClass : BaseClass
{
    public void Method1() // DerivedClass.Method1() hides inherited memeber BaseClass.Method1(). Use the new keyword if hiding was intended.
    {
        Console.WriteLine("Derived - Method1");
    }
}

想象一下,如果你写了以下内容:

var dc = new DerivedClass();
dc.Method1();

您编译并运行此代码,然后调用派生方法。但现在,删除 Method1 in BaseClass。代码仍然编译和运行完全相同。

Method1 in DerivedClass 隐藏 BaseClass 中的Method1 方法来自任何人直接使用 DerivedClass(或任何进一步派生的实例) p>

【讨论】:

    【解决方案2】:

    new 有多种用途。您参考的文档中提到的是声明修饰符。

    您在派生类中的Method1() 可以通过三种方式声明:

    public void Method1()         // 1
    public new void Method1()     // 2
    public virtual void Method1() // 3
    

    版本1和2都隐藏基类中的同名虚方法,所以在基类变量上调用时,会调用BaseClass.Method1()。但是版本 2(带有new明确隐藏了基类方法,即你告诉编译器这是故意的。第 1 版隐式隐藏了虚方法并会导致警告,因为编译器认为这可能是偶然的,而不是故意的。

    隐藏并不代表你认为的那样。这意味着在DerivedClass 及其任何后代中,Method1() 不是虚拟的,并且您不能再在DerivedClass 上调用虚拟方法。他们说 virtual 方法对DerivedClass 是隐藏的。这意味着它破坏了(继承)多态性。

    版本3覆盖同名方法,如果方法是虚拟的,则无论变量如何声明,都会调用实际方法。所以如果变量声明为BaseClass,但实际上类是DerivedClass,那么就会调用派生类的方法。

    更多信息:

    https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/new-modifier

    注意new的用法和你理解的不一样:

    BaseClass bd = new DerivedClass();
    

    这是一个不同的new不是声明修饰符

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-13
      • 1970-01-01
      • 2013-02-18
      相关资源
      最近更新 更多