【问题标题】:interface inheritance without hiding接口继承不隐藏
【发布时间】:2011-03-22 20:37:30
【问题描述】:

如果我写课,那么一切都好

class C
{
    protected int _attr;
    int attr { get { return _attr; } }
}

class CWithSet : C
{
    int attr { set { _attr = value; } }
}

但是,如果我写界面

interface I
{
    int attr { get; }
}

interface IWithSet : I
{
    int attr { set; }
}

然后我有争吵:“'IWithSet.attr' 隐藏继承的成员 'I.attr'。如果要隐藏,请使用 new 关键字。”

如何写,以免收到警告?

【问题讨论】:

    标签: c#


    【解决方案1】:

    来自 C# 规范:接口的继承成员明确地不属于接口的声明空间。因此,允许接口声明与继承成员具有相同名称或签名的成员。当这种情况发生时,派生的接口成员被称为隐藏基接口成员。隐藏继承的成员不被视为错误,但它确实会导致编译器发出警告。要抑制警告,派生接口成员的声明必须包含new 修饰符,以指示派生成员旨在隐藏基成员。 (Interface members) 正确的实现是:

    interface IWithSet : I
    {
        new int attr { get; set; }
    }
    

    【讨论】:

      【解决方案2】:

      您可能需要考虑是否值得重新定义接口的语义。我的意思是,除了你定义为“I”的只读接口之外,只拥有一个单独的只写接口可能是有意义的。

      这是一个例子:

      interface IReadOnly
      {
          int Attr { get; }
      }
      
      interface IWriteOnly
      {
          int Attr { set; }
      }
      
      interface I : IReadOnly, IWriteOnly
      {
      }
      
      class CReadOnly : IReadOnly
      {
          protected int _Attr;
          public int Attr
          {
              get { return _Attr; }
          }
      }
      
      class C : CReadOnly, I
      {
          public int Attr
          {
              get { return base.Attr; }
              set { _Attr = value; }
          }
      }
      

      编辑:我将 C.Attr 属性的 get 部分更改为 return base.Attr 而不是 return _Attr;,以便与原始问题中的代码示例更加一致。我也认为这更正确,因为您可能在 CReadOnly.Attr 中定义了您不想复制的更复杂的逻辑。

      一些接口和类已从原始示例重命名。 “I”变成了“IReadOnly”,“IWithSet”变成了“I”。 “C”变成了“CReadOnly”,“CWithSet”变成了“C”。

      这是为我编译的,没有任何警告。

      编辑:这是为我编译的,没有关于界面成员的警告。我确实收到了关于 C 类的 Attr 属性隐藏 CReadOnly 类的属性的 1 个警告,但这应该是完全可以预料的,因为在我的示例中发生了隐藏/阴影。一件奇怪的事情:我可以发誓我编译(并运行了!)这段代码几次,看到了 0 个警告。当时这让我很困惑,但我放手了……但现在我看到了 1 警告,正如我所期望的那样。也许只是编译器故障。

      【讨论】:

        【解决方案3】:

        如果您想要具有相同名称的单独属性,请使用 new。警告是不言自明的。

        另一方面,你想要的似乎更像:

        #pragma warning disable CS0108
        
        interface IWithSet : I
        {
            int attr { get; set; }
        }
        
        #pragma warning restore CS0108
        

        【讨论】:

        • int attr { 获取;放; } - 警告:“'IWithSet.attr' 隐藏继承的成员 'I.attr'。如果要隐藏,请使用新关键字。”
        • 您可以随时强制禁用警告
        • 您应该注意警告并按照它所说的去做,而不是强制禁用整个界面的警告。
        • 我必须同意tehMick,在这里。添加new 关键字不会改变行为。
        • @Eric Mickelsen:当然可以。用于救援的显式接口:interface IA { int P { get; } }interface IB : IA { new double P { get; } }class C : IB { public double P { get { return double.MaxValue; } } int IA.P { get { return int.MaxValue; } }。对不起,糟糕的格式。
        【解决方案4】:

        可能并不完美,但一种解决方案可能是:

        interface IWithSet : I
        {
            void SetAttr(int value);
        }
        

        【讨论】:

          【解决方案5】:

          怎么样:

          interface IWithSet : I
          {
              new int attr { get; set; }
          }
          

          缺点是 IWithSet 将始终同时具有 getter 和 setter,即使 'I' 中的 getter 被删除:

          interface I { }
          

          如果您在定义两个接口时假设“我”将始终拥有 getter,那么这种方法没有任何问题,这将在旨在限制访问而不是封装特定于抽象层(就像典型的读取器/写入器类型结构,在 SAFE 假设读取器具有读取权限的情况下,写入器继承了读取器的所有访问权限!)。

          【讨论】:

            猜你喜欢
            • 2014-10-06
            • 2011-10-06
            • 2013-06-11
            • 1970-01-01
            • 2012-02-13
            • 1970-01-01
            • 1970-01-01
            • 2011-04-03
            • 2017-09-21
            相关资源
            最近更新 更多