2011-03-11 55 views
4

我在使用第三方库时发现了这种行为,我需要隐藏和更改其中一种方法。为什么一个子类需要实现一个父母界面来隐藏C#中父母方法之一?

我有以下设置:

interface IBaseInterface 
{ 
    string MethodToHide(); 
} 

class BaseClass : IBaseInterface 
{ 
    public string MethodToHide() 
    { 
     return "BaseClass"; 
    } 
} 

class ChildClass : BaseClass 
{ 
    new public string MethodToHide() 
    { 
     return "ChildClass"; 
    } 
} 

为什么当我运行以下命令:

var i = (IBaseInterface) (new ChildClass()); 
Console.WriteLine(i.MethodToHide()); 

输出

BaseClass的

,但改变ChildClass签名

class ChildClass : BaseClass, IBaseInterface 

时,输出为

ChildClass

为什么我需要明确指定接口的BaseClass的方法,通过隐藏ChildClass?

+0

hidden!=被覆盖 – Greg 2011-03-11 18:43:28

回答

4

你需要阅读更多的关于之间的区别覆盖隐藏

链接:Override versus Hide

一言以蔽之:

隐藏(使用新)根据变量的类型运行该方法。
覆盖将覆盖该方法并只会使用该孩子的方法。

编辑

当你使用一个接口变量:

var i = (IBaseInterface) (new ChildClass()); 

编译器将搜索对于那些接口使用方法的最佳匹配。
由于您声明了BaseClass来实现该接口,因此将选择其方法。

如果ChildClass没有明确实现接口,则编译器无法方法链接到该接口。以其观点来看,BaseClass只是碰巧有同名的方法。

当你明确声明,ChildClass也实现了接口,那么它的方法将是最好的选择。

+0

是的,但我对行为感兴趣,在这种情况下,我无法重写该方法。在ChildClass的实例中,它被转换为接口,而不是基类。那么为什么它是编译器选择的基类的方法呢? – 2011-03-11 18:51:46

+0

因为编译器的最佳选择是显式声明方法属于接口的BaseClass。从编译器的角度来看,childclass恰好有一个同名的方法。 – 2011-03-11 18:55:10

+0

我已经添加了一些关于此的答案 – 2011-03-11 19:01:17

2

您需要在您的BaseClass中将MethodToHide标记为虚拟。然后你的ChildClass可以覆盖它。有关更多详细信息,请参阅http://msdn.microsoft.com/en-us/library/9fkccyh4(v=vs.80).aspx

我相信这是规范的相关部分:

10.6.3虚拟方法在虚拟方法调用中,实例的运行时类型 针对该 调用发生确定 的实际方法实现为 调用。在一个非虚方法 调用中,编译时类型 该实例是确定 的因子。

所以,当你将原始对象投射到IBaseInterface。它确定类型是BaseClass,因为那是实现它并调用它的方法的类型。在第二个示例中,它将其解析为ChildClass并调用其方法。

+1

我相信OP是* explicity *询问隐藏,而不是覆盖。 – 2011-03-11 18:43:59

+0

因为BaseClass是第三方封闭源库的一部分,所以我无法做到这一点。而且我知道我可以这样做,我正在询问这种行为。 – 2011-03-11 18:49:04

1

因为主类实现了接口。子类只是定义了一个新的方法,与接口无关。事实上,孩子班级隐藏了这种方法 - 这就是“新”的做法。

相关问题