using System;
namespace random
{
interface IHelper
{
void HelpMeNow();
}
public class Base : IHelper
{
public void HelpMeNow()
{
Console.WriteLine("Base.HelpMeNow()");
}
}
public class Derived : Base
{
public new void HelpMeNow() ///this line
{
Console.WriteLine("Derived.HelpMeNow()");
}
}
class Test
{
public static void Main()
{
Derived der = new Derived();
der.HelpMeNow();
IHelper helper = (IHelper)der;
helper.HelpMeNow();
Console.ReadLine();
}
}
}
注释行中的新关键字对我来说有点混乱。它jsut意味着它覆盖了基类中方法的实现。 为什么不使用override关键字?
答案 0 :(得分:9)
在MSDN上查看此文章:Knowing When to Use Override and New Keywords
答案 1 :(得分:0)
它并没有真正压倒它,它是阴影它。如果引用了Derived
对象,Base
的{{1}}函数将无法访问 1 ,HelpMeNow
将调用derivedObject.HelpMeNow()
的实施。
这与覆盖虚拟函数不同,Derived
不是。如果HelpMeNow
对象存储在Derived
或Base
的引用中,则会调用IHelper
的{{1}},Base
1}}的实现将无法访问。
HelpMeNow()
当然,如果上述不是所希望的行为,而且通常不是,那么有两种可能性。如果您控制Derived
,只需将Derived derivedReference = new Derived();
Base baseReference = derivedReference;
IHelper helperReference = derivedReference;
derivedReference.HelpMeNow(); // outputs "Derived.HelpMeNow()"
baseReference.HelpMeNow(); // outputs "Base.HelpMeNow()"
helperReference.HelpMeNow(); // outputs "Base.HelpMeNow()"
更改为虚拟,并在Base
中覆盖它,而不是隐藏它。如果您不控制HelpMeNow()
,那么您至少可以通过重新实现Derived
来解决问题,如下所示:
Base
此版本的IHelper
使用所谓的显式接口实现,它允许您满足实现接口的合同,而无需将实现添加到类的公共接口。在这个例子中,我们已经在class Derived : Base, IHelper{
public new void HelpMeNow(){Console.WriteLine("Derived.HelpMeNow()");}
void IHelper.HelpMeNow(){HelpMeNow();}
}
的公共接口中有一个继承自Derived
的实现,所以我们必须明确地实现Derived
来改变它 2 。在这个例子中,我们只是将Base
的实现转发到我们的公共接口,这是IHelper
的阴影。
因此,通过此更改,对IHelper.HelpMeNow
的调用仍会输出“Base.HelpMeNow()”,但调用Base
现在将输出“Derived.HelpMeNow()”。不如将baseReference.HelpMeNow()
的实现更改为虚拟,但如果我们不控制helperReference.HelpMeNow()
那么就好了。
1 例外: 可以从Base
的方法中访问,但只有在使用Base
进行限定时才能访问如Derived
。
2 请注意,我们还必须声明base.
作为类实现的接口,即使我们从base.HelpMeNow()
继承此声明。功能
答案 2 :(得分:0)
通常,如果接口IBase实现成员DoSomething,并且IDerived继承/实现Ibase,则它期望IDerived.DoSomething将与IBase.DoSomething同义。通常,这很有用,因为它使类的实现者不必提供冗余实现。但是,在某些情况下,派生接口必须实现一个与基接口中的成员同名的成员,但必须单独实现。最常见的这种情况是(1)派生方法将具有与基类型不同的返回类型,或者(2)基本接口实现具有特定和派生的ReadOnly和/或WriteOnly属性。 type应该实现Read-Write属性。无论出于何种原因,如果接口IReadableFoo提供只读属性Foo,IWritableFoo提供只写属性Foo,并且接口IMutableFoo只是继承两者,编译器将不知道对Foo的引用是否引用IReadableFoo.Foo或IWritableFoo。富。尽管只能读取IReadableFoo.Foo,并且只能写入IWritableFoo.Foo,但vb.net和C#都不能解决重载问题,除非有人实现处理这两者的新的读写属性Foo。