C#菱形继承(接口实现)

C#菱形继承(接口实现),c#,inheritance,diamond-problem,interface-implementation,C#,Inheritance,Diamond Problem,Interface Implementation,如果一个类从两个独立的接口实现一个接口,它的行为是否完全像只实现一次一样 例如: public interface IAnimal { /* ... */ } public interface IFullAnimal : IAnimal { /* ... */ } public interface IBear : IAnimal { /* ... */ } public interface IFullBear : IBear, IFullAnimal { /* ... */ } // and

如果一个类从两个独立的接口实现一个接口,它的行为是否完全像只实现一次一样

例如:

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

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

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

上面,
IFullBear
通过
IFullBear
IFullAnimal
IBear
实现
IAnimal
。由于
IFullAnimal
IBear
都没有提供任何关于
IAnimal
实现的信息(因为语言不允许这样),这是否会导致IAnimal的实现出现任何奇怪的行为,如果
IA
IB
都继承自
IX
,并且一个类实现了这两者,那么“由
IA
继承的
IX
的成员”和“由
IB
继承的
IX
的成员”之间没有区别。所有这些成员都只是
IX
的成员。此外,声明为实现
IA
IB
IX
的类与仅声明为实现
IA
IB
的类之间没有区别,因为实现
IA
IB
的任何类,或者两者都必须实现
IX
,无论是否声明这样做


NET接口继承模型避免了“菱形问题”,因为中级接口无法向继承的接口添加任何东西,从而将它们与这些相同接口的任何其他继承版本区分开来。Java的模型也用来避免菱形问题,但通过允许中级接口声明默认方法,Java的更高版本使致命的菱形层次结构成为可能。

不,这是一种非常常见且无害的场景
System.Collections.Generic
namespace是类似“冗余”接口声明的一个很好的例子:

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

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!  !!!

那么
接口IA{}接口IB:IA{}接口IC:IA,IB{}
呢。这些与实施有什么关系?您做出了多个承诺,表示该类拥有成员
IAnimal
承诺。好的。
IFullBear
没有实现任何东西,它是一个接口。因此,您的意思是:多个承诺“实现我的东西必须实现
IAnimal
”不能潜在地导致在
IAnimal
中声明的方法/属性的多个实现?多个实现从何而来?类实现或不实现接口。为什么语言的设计者会这样设计呢?为什么编译器会对一些容易检测的东西绝对沉默?不要把它与C++多重继承混淆起来。C禁止特定的多个类继承,因此在同一个类中不能有多个冲突的实现,特别是为了防止C++菱形继承问题。谢谢
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!  !!!