我在使用第三方库时发现了这种行为,我需要隐藏并更改其中一种方法。
我有以下设置:
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
为什么我需要明确指定ChildClass隐藏的BaseClass方法的接口?
答案 0 :(得分:4)
您需要详细了解覆盖与隐藏之间的区别:
简而言之:
隐藏(使用新的)根据变量的类型运行方法 覆盖会覆盖该方法,并且只会使用子方法。
修改强>:
使用Interface变量时:
var i = (IBaseInterface) (new ChildClass());
编译器将搜索接口使用的方法的最佳匹配 因为您声明 BaseClass 来实现接口,所以将选择其方法。
如果 ChildClass 没有显式实现接口,则编译器无法将方法链接到接口。从它的角度来看, BaseClass 碰巧有相同名称的方法。
当显式声明 ChildClass 也实现了接口时,其方法将是最佳选择。
答案 1 :(得分:2)
您需要在BaseClass中将MethodToHide标记为虚拟。然后你的ChildClass可以覆盖它。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/9fkccyh4(v=vs.80).aspx。
我相信这是规范的相关部分:
10.6.3虚拟方法在虚方法调用中,运行时类型 对此的实例 调用发生决定了 实际的方法实现 调用。在非虚方法中 调用,编译时类型 实例是决定因素 因素。
因此,当您将原始对象转换为IBaseInterface时。它确定类型是BaseClass,因为它是实现它并调用其方法的类型。在第二个示例中,它将其解析为ChildClass并调用其方法。
答案 2 :(得分:1)
因为main-class实现了接口。子类只定义了一个与接口无关的新方法。实际上,子类隐藏了该方法 - 这就是'新'所做的。