为什么新的“隐藏”基类方法?

时间:2018-01-29 12:01:54

标签: c#

我的术语有问题。根据MSDN:“覆盖修饰符扩展了基类方法,新修饰符隐藏了它。” 但是,在以下示例中:

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()时使用覆盖,bd.Method1()将按照派生类中的指示输出:“Derived - Method1”。

为什么每个来源(包括官方文档)都说 隐藏 基础类方法,在此示例中明确表示基础class方法是使用new?

时调用的方法

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

2 个答案:

答案 0 :(得分:1)

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上调用虚拟方法。他们说虚拟方法隐藏在DerivedClass之内。这意味着它打破(继承)多态。

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

更多信息:

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

请注意,new的使用与您理解的不同:

BaseClass bd = new DerivedClass();

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

答案 1 :(得分: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中的 BaseClass。代码仍然编译并运行完全相同。

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