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