c#中接口中的新词

时间:2009-08-27 00:01:46

标签: c# interface

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关键字?

3 个答案:

答案 0 :(得分:9)

在MSDN上查看此文章:Knowing When to Use Override and New Keywords

答案 1 :(得分:0)

它并没有真正压倒它,它是阴影它。如果引用了Derived对象,Base的{​​{1}}函数将无法访问 1 HelpMeNow将调用derivedObject.HelpMeNow()的实施。

这与覆盖虚拟函数不同,Derived不是。如果HelpMeNow对象存储在DerivedBase的引用中,则会调用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。