C#Diamond-Inheritance(接口实现)

时间:2017-11-09 19:23:08

标签: c# inheritance diamond-problem interface-implementation

如果一个类从两个独立的接口实现一个接口,它的行为就像它只实现一次一样吗?

示例:

public interface IAnimal { /* ... */ }
public interface IFullAnimal : IAnimal { /* ... */ }

public interface IBear : IAnimal { /* ... */ }
public interface IFullBear : IBear, IFullAnimal { /* ... */ }

// and implementing IFullBear:
public class FullBear : IFullBear { /* ... */ }

在上方,FullBearIAnimalIFullAnimalIBear实施IFullBear。这是否会引入任何有关IAnimal 实现的奇怪行为,因为IFullAnimalIBear都没有提供有关IAnimal 实现的任何信息(正如语言所做的那样)不允许)。

2 个答案:

答案 0 :(得分:3)

在.NET中,如果IAIB都从IX继承并且一个类实现了两者,那么“IX继承的成员之间没有区别。 IA“和”IX继承的IB“。所有这些成员都只是IX的成员。此外,声明为实现IAIBIX的类与仅声明为实现IA和{{}的类之间没有区别。 1}},因为任何实现IBIA或两者的类都必须实现IB,无论它是否被声明为这样做。

接口继承的.NET模型避免了“钻石问题”,因为中级接口无法向继承的接口添加任何东西,以区别于那些相同接口的任何其他继承版本。 Java的模型过去也避免了钻石问题,但是通过允许中级接口声明默认方法,Java的后续版本可以使致命钻石层次结构成为可能。

答案 1 :(得分:2)

不,这是一种非常普遍且无害的情况。 System.Collections.Generic命名空间是类似"冗余"的一个很好的例子。接口声明:

 public class List<T> : IList<T>, 
                        System.Collections.IList,
                        IReadOnlyList<T>

IList<T>IReadOnlyList<T>显然都在实施IEnumerable<T>,而且世界还没有结束。

不要将此与接口重新实现混淆,这会改变行为:

interface IFoo
{
    void Foo();
}

class Base: IFoo
{
     public void Foo() { Console.WriteLine("Base Foo!");
}

class Derived: Base { }

class DerivedWithATwist: Base, IFoo //redeclares interface
{
    void IFoo.Foo() { Console.WriteLine("Derived Foo!");
}

现在,

IFoo foo = new Base();
IFoo derived = new Derived();
IFoo derivedWithATwist = new DerivedWithATwist();

foo.Foo(); //Base Foo!
derived.Foo(); //Base Foo!
derivedWithATwist.Foo(); //Derived Foo!
(derivedWithATwist as Base).Foo(); //Base Foo!  !!!