【问题标题】:Why can I seal a class implementing an interface but cant seal a member?为什么我可以封装实现接口的类但不能封装成员?
【发布时间】:2011-05-25 18:05:09
【问题描述】:

给定这个接口

public interface IMyInterface
{
    string Method1();
}

为什么这是有效的

public sealed class InheretedFromInterfaceSealed: IMyInterface
{
    public string Method1()
    {
        return null;
    }
}

但这不是

public class InheretedFromInterfaceWithSomeSealed: IMyInterface
{
    public sealed string Method1()
    {
        return null;
    }
}

然而对于抽象类来说这是一个有效的场景

public abstract class AbstractClass
{
    public abstract string Method1();
}
public class InheretedFromAbstractWithSomeSealed: AbstractClass
{
    public sealed override string Method1()
    {
        return null;
    }
}

【问题讨论】:

    标签: .net inheritance interface virtual sealed


    【解决方案1】:

    因为默认情况下每个方法都是密封的,除非它是虚拟的,或者除非你没有在已经是虚拟的并且你正在覆盖的东西上说 sealed

    【讨论】:

    • 让我感动的是我正在从抽象类转换为接口并将成员标记为密封在抽象类场景中是有效的。见编辑。
    • 嗯,好的。是的,我也愣了一会儿,直到我意识到发生了什么。 :)
    【解决方案2】:

    默认情况下,类中的每个方法都是密封的(VB.NET 中为NotOverridable),除非您明确将其声明为virtual(VB.NET 中为Overridable)。

    正如你所说,不是类的情况。您必须明确指出要禁止使用sealed(或VB.NET 中的NotInheritable)从类继承。

    【讨论】:

      【解决方案3】:

      提醒一下,C#中的接口方法不能是sealed

      考虑以下代码:

      interface IFoo
      {
          void Bar();
      }
      class Base : IFoo
      {
          public void Bar() { Console.WriteLine("Base.Bar"); }
      }
      class Derived : Base, IFoo
      {
          public new void Bar() { Console.WriteLine("Derived.Bar"); }
      }
      

      然后,如果我们有var d = new Derived(),我们将有:

      • d.Bar() 写信 Derived.Bar
      • ((Base)d).Bar()Base.Bar
      • ((IFoo)d).Bar() 写信 Derived.Bar
      • ((IFoo)(Base)d).Bar()Derived.Bar

      接口方法Bar被派生类覆盖。 sealed的方法不是接口方法,而是Base的方法。

      也就是说,隐式实现

      class ImplicitImpl : IFoo
      {
          public void Bar() { Blah; }
      }
      

      应该被认为是以下语义等价的显式实现:

      class ImplicitImplEquiv : IFoo
      {
          public void Bar() { Blah; }
          void IFoo.Bar() { this.Bar(); }
      }
      

      如果ImplicitImplEquiv 的派生类只是用另一个public void Bar 隐藏public void Bar,调用((IFoo)ref).Bar() 仍将调用ImplicitImplEquiv.Bar。但是如果派生类也重新继承IFoo并提供新的实现,接口vtable将与ImplicitImplEquiv不同。

      【讨论】:

        猜你喜欢
        • 2018-11-25
        • 1970-01-01
        • 1970-01-01
        • 2012-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多