有没有理由在界面中隐藏继承的成员?

时间:2010-08-25 21:58:58

标签: c# .net polymorphism interface

我知道从另一个类继承的类可能会使用new关键字隐藏属性。但是,这隐藏了属性的特定实现,因此我可以看到它是如何使用的。

是否有任何实际的理由在实现其他接口的接口中隐藏成员?例如,考虑以下示例。 IChildInterface实施IParentInterface,并隐藏PropertyA

interface IParentInterface
{
    string Name { get; set; }
    int PropertyA { get; set; }
    int PropertyB { get; set; }
}

interface IChildInterface : IParentInterface
{
    int PropertyA { get; set; }
    int PropertyC { get; set; }
}

5 个答案:

答案 0 :(得分:23)

  

是否有任何实际的理由在实现其他接口的接口中隐藏成员?

不确定。 BCL本身使用这种模式的事实表明该模式是实用的。例如:

interface IEnumerable 
{ 
    IEnumerator GetEnumerator();
}
interface IEnumerable<T> : IEnumerable
{
    new IEnumerator<T> GetEnumerator();
}

IEnumerable<T>的设计者希望与IEnumerable向后兼容,但也希望确保通用接口上GetEnumerator的每次使用都称为通用版本。在这种情况下,隐藏是适当的机制。

关于方法隐藏的细微之处的一些额外讨论,请参阅:

http://blogs.msdn.com/b/ericlippert/archive/2008/05/21/method-hiding-apologia.aspx

答案 1 :(得分:7)

我发现隐藏基本成员有用的一个案例是当你有一个基本接口,它在属性上公开一个getter但是派生接口想要暴露一个setter:

public interface IBase
{
   int MyProperty { get; }
}

public interface IDerive : IBase
{
    // you need to specify the getter here too
    new int MyProperty { get; set; }
}

答案 2 :(得分:2)

接口不能完全隐藏父接口,但实现类可以,这可能很有用。

考虑一个类MyStringList,它是一个实现IList<string>的只读列表。为简单起见,我们将它作为一个简单的传递:一些成员是毫无意义的,所以我们可以这样做:

//implement this one implicitly, as it's useful.
public int Count
{
  return _list.Count;
}
//do a half-and-half on the indexer
public string this[int index]
{
  get
  {
    return _list[index];
  }
}
string IList<string>.this[int index]
{
  get
  {
    return this[index];
  }
  set
  {
    throw new NotSupportedException("Collection is read-only.");
  }
}
//hide some pointless ones.
bool ICollection<string>.IsReadOnly
{
  get
  {
    return true;
  }
}
void IList<string>.Insert(int index, string item)
{
  throw new NotSupportedException("Collection is read-only.");
}
void IList<string>.RemoveAt(int index)
{
  throw new NotSupportedException("Collection is read-only.");
}
void ICollection<string>.Add(string item)
{
  throw new NotSupportedException("Collection is read-only.");
}
void ICollection<string>.Clear()
{
  throw new NotSupportedException("Collection is read-only.");
}
bool ICollection<string>.Remove(string item)
{
  throw new NotSupportedException("Collection is read-only.");
}

处理MyStringListIList<string>界面的人必须能够调用这些毫无意义的成员,但是没有必要与MyStringList打交道。

现在,有了这个可能的类,接口可以通过名称匹配父接口强制这样的含义。类示例为IEnumberable<T>,其中GetEnumerator()与其继承的IEnumerable匹配。因此,类可以隐式地只实现一个,并且必须隐藏另一个或两个(因为总是可以将结果(IEnumerator<T>)转换为另一个的结果类型(IEnumerator)然后最明智的行为通常是隐式实现IEnumberable<T>版本,并明确地实现IEnumerable一个(通常通过返回另一个的结果)。

然而,虽然隐藏的力量至少有一个被隐藏,但没有什么可以强制选择哪个(如果有的话)是隐式实现的,除了一个具有如此明显的优势而另一个没有那么少的人。

答案 3 :(得分:1)

隐藏继承的成员不应该故意作为设计的一部分。语言允许隐藏方法,以防止祖先(在库的主要版本中)发生更改,从而破坏恰好已经定义了相同名称的成员的后代。

也就是说,有时使用返回更具体类型的等效方法隐藏继承的方法很方便。在这些情况下,你唯一要做的就是强制转换糖 - 注意不要改变方法的语义,因为调用者可能很容易调用祖先方法而不是你的方法。

另请参阅:Is there ever a situation where derived class should hide …?

答案 4 :(得分:0)

我想如果你要明确地实现IChildInterface,可能会出现你想要隐藏PropertyA的情况(可能?)