方法隐藏(new)与重写(override)的一道面试题

bigbro001 2011-08-31 10:04:59

class A
{
public virtual void F()
{
Console.WriteLine("A.F");
}
}

class B : A
{
public override void F()
{
Console.WriteLine("B.F");
}
}

class C : B
{
new public virtual void F()
{
Console.WriteLine("C.F");
}
}

class D : C
{
public override void F()
{
Console.WriteLine("D.F");
}
}


class Program2
{
static void Main()
{
D d = new D();
A a = d;
B b = d;
C c = d;

a.F();
b.F();
c.F();
d.F();
}
}


以上这段代码中,主方法中的四个引用a, b,c,d都是指向同一个D对象,c和d因为重载方法的动态绑定,输出结果相同,可以理解,可是为什么a和b的输出结果却和c,d不一样呢?

请问哪位前辈可以指点一二?
...全文
347 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
bigbro001 2011-09-06
  • 打赏
  • 举报
回复
非常感谢各位前辈的指点!
feixuyue 2011-09-06
  • 打赏
  • 举报
回复
  • 打赏
  • 举报
回复
学习了,caozhy的比喻很生动形象,theillusion的解释也很详细。。。
膜拜一下
freedom_wyz 2011-09-06
  • 打赏
  • 举报
回复
A中F()的最终实现到B,C中F()的最终实现到D,C中F()屏蔽掉了A中的F(),所以任何C的子类调用F()会调用D中的F(),任何A的子类但非C的子类调用F()会调用B中的F()。
bigbro001 2011-09-06
  • 打赏
  • 举报
回复
多谢caozhy前辈和18楼的大侠的指教!
sb1ue 2011-09-06
  • 打赏
  • 举报
回复
学习了,果然基础还是不牢阿。。
krenyelang 2011-09-06
  • 打赏
  • 举报
回复
技术参考……
bios8086 2011-09-06
  • 打赏
  • 举报
回复
自己试着重写了个类似的小程序!还是有些收获的!
呵呵
萧炎 2011-09-06
  • 打赏
  • 举报
回复
LZ 我看了你的题目和回复的次数 我就知道来迟了 肯定有高人解决了

唉。。。。。
threenewbee 2011-09-01
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 q107770540 的回复:]
我实在搞不明白 考这样的面试题 目的是什么
蛋疼是不
[/Quote]

我写了那么多程序,几乎没有用到过方法隐藏。我真不知道发明这个题目的人怎么考虑的。这是一个常用的基本的语法现象和一个罕见的,几乎用不到的东西放在一起讨论的问题。

如同你的钱包在汽车上没了,探讨到底是被小偷拿走了还是被奥特曼拿走了一样。
极地_雪狼 2011-09-01
  • 打赏
  • 举报
回复
唉,又一悲催的面试题。不知道是要考核还是要显示出题人的水准。
vrhero 2011-09-01
  • 打赏
  • 举报
回复
因为new截断了继承链,从此开始派生类的该成员和基类没有关系了,仅仅是签名相同而已...而这些发生在运行期,跟编译器蛋关系都没有...

这些是C#最基础的概念之一...这种题不适合做面试题,就像小学升初中考1+1一样...
theillusion 2011-09-01
  • 打赏
  • 举报
回复
a.F();

这个调用,编译时类型是 A,运行时类型是D,正常情况下,在运行时确定 F 版本的顺序是:A.F -> B.F -> C.F -> D.F,如果运行时类型与这个链条中的某一环匹配,被调用的的方法就确定了。但是,这个面试题里面 C.F 是 new 的(他是 new 的,多么可爱的草泥码),因此继承链被打断,变成这样: A.F -> B.F, C.F -> D.F,因此,a.F 的确定过程,只能到 B.F 就停止了。

其实C#里这个new就是用来抽筋的,打断继承链弄点匪夷所思的效果,以便使某些技术大牛可以专门弄些违反里氏替换原则的面试题,在鄙视和误导(他们眼中的)小菜之余感觉自己很酷很新潮。

py1025677845 2011-09-01
  • 打赏
  • 举报
回复
都显示了出题人的水平了,扯淡。。。
threenewbee 2011-09-01
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 bigbro001 的回复:]
多谢楼上前辈的指点。。。晚辈这个钻牛角尖的坏习惯被前辈指出了,见笑了。。。前辈举出的例子,小弟要回去好好体会体会。。。
[/Quote]
不是指责你钻牛角尖。探索精神是值得鼓励的。问题是,要把基本的学好。否则会绕弯路,不得要领。因为你“探索”的东西,是前人已经搞明白的,你是在做无效劳动。
Tim_Andy 2011-09-01
  • 打赏
  • 举报
回复
我说的够通俗不。
Tim_Andy 2011-09-01
  • 打赏
  • 举报
回复
这么说把,重写是直接把原来的方法覆盖掉。就算显示调用父类的方法也是你重写后的那个。
隐藏的话,当你显示调用父类的方法还是可以调用的。
bigbro001 2011-09-01
  • 打赏
  • 举报
回复
多谢楼上前辈的指点。。。晚辈这个钻牛角尖的坏习惯被前辈指出了,见笑了。。。前辈举出的例子,小弟要回去好好体会体会。。。
threenewbee 2011-09-01
  • 打赏
  • 举报
回复
你应该认识到,方法覆盖是OO设计中大量用到的特性。无论是C#还是C++还是Java,无论是使用虚表技术还是反射还是运行时绑定。换一句话说,这个需求理应在你学习一门语言,乃至实现原理之前就应该理解。

还是照相机的比喻,你在探讨的是,为什么按下快门得到照片,而不是从镜头里面射出子弹。这不是某个相机内部构造的问题,而是你买来相机,就是期望拍出照片而不是射出子弹。即便你不懂照相机的原理,即便你还没有买照相机,从你走进商店的那时候起,你就对你要买的东西做什么应该是清楚的。

所以从你的思考角度,作为面试题,一看你就是从来没有写过程序,没有工作经验的。

如果你用Java写过程序,你的思维角度是,我就是需要一个机制,可以让子类对象的方法覆盖掉父类的方法。在C#里面怎么做。如果找到这么一个语法能做,那么问题就解决了,而不是反过来,某某语法会被怎么执行。如同我用过SONY的相机,它的快门是在机器的侧面,我现在换奥林巴斯的相机,它的快门在哪里。而不是问,为什么按了奥林巴斯的快门能得到照片,按了设置键却会弹出一个菜单。
threenewbee 2011-09-01
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 bigbro001 的回复:]
各位前辈,对不住了,晚辈刚刚从Java转过来的,对new,virtual,override这些概念还不是很熟,所以想诚恳的请教各位前辈,当碰到a.F()这句话的时候,编译器的具体处理过程是怎样的,不知道可以这么理解吗:

1.编译器去引用a所属的类A中寻找方法F(),发现是virtual,于是继续向A->D继承链的下一个类B中去寻找方法F()
2.在B类的方法F中,编译器没有发现virtua……
[/Quote]
不可以这么理解。
事实上,调用哪个方法是运行时确定的。

如果是编译器决定的,那么就悲剧了。设想,我们设计一个插件系统。我们开发好主程序,允许第三方开发者为我们设计一个插件。我们看到如下的代码:

PluginBase p = LoadPluginFromDll("x:\plugin1.dll");
p.CallPlugin();


在 Plugin 里面有如下代码:
class Plugin1 : PluginBase
{
public override void CallPlugin() { ... }
}


显然在主程序里面,是看不到plugin1这个库的信息的,甚至plugin1还没有写出来(否则也谈不上插件了)。如果是编译器决定的,那么显然p.CallPlugin()执行的是PluginBase里面的那个方法。

你觉得这样的语言能满足你的需要么?如同一个照相机,如果它的说明书上写,我们照相的原理是厂家拍好照片存在机器里面,你按下快门调一张出来,你会买这个照相机么?这是一个浅显的道理。语言其实就是工具,不是说不应该刨根问题,而是说,你连它干什么的都不知道的情况下刨根问底显得很可笑。

不过退一步说,也没有必要理解。所谓从Java转过来,只能说你Java完全不懂。
如同我们使用一部数码相机,并不需要理解它是怎么成像的。按下快门,得到照片就这么简单。你说你从机械相机转到数码相机,连快门是干什么用的都不知道,是不是很荒谬。
事实上,方法隐藏是一个几乎用不到的特性,如同相机被当作砖头作为防身手段是极其罕见的用途。你不用去理解相机什么时候被当作砖头,什么时候可以拍照。
加载更多回复(6)

110,580

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧