【问题标题】:C# Diamond-Inheritance (Interface Implementation)C# Diamond-继承(接口实现)
【发布时间】:2017-11-09 19:23:07
【问题描述】:

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

例子:

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

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

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

在上面,FullBearIFullAnimalIBearIFullBear 都实现了IAnimal。这是否会引入有关 IAnimal 实现的任何奇怪行为因为IFullAnimalIBear 都没有提供有关IAnimal 实现的任何信息(因为语言不允许这样做)。

【问题讨论】:

  • interface IA { } interface IB : IA { } interface IC : IA, IB { } 怎么样。这与实施有什么关系?您正在做出多个承诺,即该类具有成员 IAnimal 承诺。好的。
  • IFullBear 没有实现任何东西,它是一个接口。
  • 所以,你是说:“无论实现我什么都必须实现IAnimal”的多个承诺不能潜在地导致IAnimal 中声明的方法/属性的多个实现?
  • 多个实现从何而来?一个类实现或不实现接口。为什么语言的设计者会这样设计它?为什么编译器会对如此容易检测的事情保持沉默?
  • 不要将此与 C++ 多重继承混为一谈。 C# 专门禁止从多个类继承,因此同一个类中不能有多个冲突的实现,特别是为了防止 C++ 菱形继承问题。

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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

    IList&lt;T&gt;IReadOnlyList&lt;T&gt; 显然都实现了IEnumerable&lt;T&gt;,世界还没有结束。

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

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

    【讨论】:

    • 接受现有示例和示例代码的此答案。谢谢!
    猜你喜欢
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-17
    • 2021-01-29
    相关资源
    最近更新 更多