普遍的误解:不是没有的替代(译文)
By S.F.
本文链接 https://www.kyfws.com/news/popular-misconception-the-override-that-was-not/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 3 分钟阅读 - 1276 个词 阅读量 0普遍的误解:不是没有的替代(译文)
原文地址:https://www.codeproject.com/Articles/47495/Popular-Misconception-The-Override-That-Was-Not
原文作者:Joel Ivory Johnson
译文由本站翻译
前言
不是的替代
上周我正在面试工作,在所有面试中,我都遇到了有关面向对象技术和C#的问题.当被问及在未标记为虚拟的类上重写方法时,我通知访问者无法完成该方法.直到昨天,当一个面试官向我提供他正在寻找的答案时,我才意识到面试官认为我的答案是错误的.他告诉我,我可以通过在其上使用new
关键字来覆盖原本不可替代的方法.这就开始了讨论,导致面试官想知道该方法是否真的有效地被覆盖了.与他讨论之后,我意识到早期的面试官可能还认为我的答案不正确.
误解来自对一种方法使用" new"关键字时会发生什么的观察.为了使讨论更加具体,我将分享一些示例代码.
class MyBase
{
public virtual string MethodA()
{
return "Hello from MethodA";
}
public string MethodB()
{
return "Hello from MethodB";
}
}
这个类的作用很明显,它有两个方法都返回一个唯一的字符串.该类非常简单,当我说它可靠地完成工作且没有错误时,我相信您会相信我的.其中一种方法被标记为"虚拟",因此它是可重写的.另一个不是.所以现在,我从该基类派生一个类.
class Derived : MyBase
{
public override string MethodA()
{
return "Hello from Derived::MethodA";
}
public new string MethodB()
{
return "Hello from Derived::MethodB";
}
}
在这个派生类中,我重写了MethodA
.由于" MethodB"没有被标记为虚拟的,因此我无法覆盖它,因此我使用了" new"关键字.让我们测试程序,看看它产生什么类型的输出.
static void Main(string[] args)
{
var a = new Derived();
var b = new MyBase();
Console.Out.WriteLine(b.MethodA());
Console.Out.WriteLine(b.MethodB());
Console.Out.WriteLine(a.MethodA());
Console.Out.WriteLine(a.MethodB());
}
运行此命令的输出就是预期的结果.当我调用MethodA和MethodB时,将显示派生类中派生的string.
Hello from MethodA
Hello from MethodB
Hello from Derived::MethodA
Hello from Derived::MethodB
看到这种行为后,我上周与开发人员交谈的开发人员似乎认为这等同于重写的功能.但是,当通过"接口"或基类引用处理类的实例时,就会显示出区别.假设我将以下内容附加到上面的代码中:
var c = a as MyBase;
Console.Out.WriteLine(c.MethodA());
Console.Out.WriteLine(c.MethodB());
输出与我们期望的重写方法所产生的结果不一致.
Hello from Derived::MethodA
Hello from MethodB
上面的输出表明,当方法被重写时,无论与对象实例进行交互的"接口"如何,都将调用该方法. " MethodA"已被覆盖,因此即使使用类型为基类的变量,也会调用覆盖的实现. " MethodB"从未真正被覆盖过,因此当使用基类引用时,将调用基类实现.
那么,new
关键字到底做了什么呢?它允许某人创建一个与现有方法具有相同签名和名称的方法.虽然使用与调用原始方法时相同的符号来调用方法,但实际上并没有执行重写.它只是隐藏它.为了进行确认,还可以查看CSDN文档中MSDN上" new"关键字的内容,该关键字将其称为名称隐藏.
http://msdn.microsoft.com/zh-CN/library/51y09td4(VS.71).aspx#vclrfnew_newmodifier.aspx#vclrfnew_newmodifier)
深入研究文档,我们发现以下内容:
结论:" new"关键字没有执行覆盖,它是作用域运算符.
CodeProject
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# Dev Intermediate 新闻 翻译