1

我正在研究接口,并且在某个时候我来到了显式接口实现。在大约 2:55的一个教程视频中,它说当一个类继承 2 个不同的接口时,如果这两个接口具有同名的方法,那么将调用哪个接口的方法存在歧义。

using System;

interface I1
{
    void InterfaceMethod();
}

interface I2
{
    void InterfaceMethod();
}

public class Program : I1, I2
{
    public void InterfaceMethod()
    {
        Console.WriteLine("I1 Interface Method");
    }

    public static void Main()
    {
        Program p = new Program();
        p.InterfaceMethod();
    }
}

我很困惑,因为接口没有方法定义,那么为什么调用哪个接口的方法很重要?两种方法同名。

4

3 回答 3

2

调用哪个很重要,因为尽管接口方法可能具有相同的名称(以及参数甚至返回类型),但它们在这些不同接口的上下文中可能具有完全不同的含义。因此,您必须能够为每个接口指定要使用的实现方法。

例如:

interface IVehicle
{
    int GetNumberOfWheels();
    int GetNumberOfDoors();
}

interface ICheeseContainer
{
    int GetNumberOfWheels();
    int GetNumberOfWedges();
}

class CheeseDeliveryTruck : IVehicle, ICheeseContainer
{
    // Object has to be able to return the number of wheels on the truck
    // when used as an IVehicle.

    // Object has to be able to return the number of cheeses in the back of
    // the truck which are packaged as wheels when used as an ICheeseContainer.
}
于 2018-01-12T16:38:19.747 回答
2

为什么调用哪个接口的方法很重要?两种方法同名。

也许没关系。但也许不是。

在这种情况下,该方法的结果是输出“I1 接口方法”,表明在实际代码中等价物确实关心它是I1.

当我们创建方法时,我们会根据一个词或几个词在自然语言(如英语)中的含义,给它们起简短而清晰的名称。这实际上可能导致两个具有相同名称的方法的目的不同(无论是非常不同还是微妙地不同)。然后我们希望有单独的实现。

当事情排成一行时很好,这样我们确实可以对两者使用相同的方法,但在不合适的时候我们不会被困住也很好。

对于具有相同名称和参数签名但返回类型不同的方法的接口,我们还必须有单独的实现,因为 C# 无法区分这些。一个常见的例子是IEnumerable<T>因为它有一个GetEnumerator()返回的方法,IEnumerator<T>但继承自IEnumerable它有一个GetEnumerator()返回的方法IEnumerator。(IEnumerator<T>并且IEnumerator也是同样原理的例子)。

我们可能想要进行显式接口实现的另一种情况是成员在具体类型的上下文中不是很有用。例如List<T>实现ICollection<T>. 该接口具有在直接IsReadOnly使用的上下文中没有意义的属性,List<T>因为我们知道它是错误的,因为List<T>s 本质上不是只读的。但是,当我们处理ICollection<T>引用时,这很重要(当然,规则要求它以一种或另一种方式实现),因此它是作为显式实现完成的。ReadOnlyCollection<T>不仅做同样的事情(当然,返回true而不是false),而且使类似的方法Add()显然毫无意义,因为无论如何它们总是会抛出异常,显式的。

于 2018-01-12T17:02:51.920 回答
1

看起来你正在使用 C#。所涉及的语言对于这个问题非常重要。我建议在问这样的问题时为此添加一个标签。

我相信 C# 将其视为模棱两可的引用,而不是仅仅对两者使用相同的实现的原因是

  1. 如果你必须在你的实现类中声明这两个方法,那么同名的两个方法可以有不同的返回类型,所以同一个系统可以用于更广泛的问题。

    interface I1 { 
        int Foo();
    }
    
    interface I2 {
        string Foo();
    }
    
    class C : I1, I2 {
        int I1.Foo() { ... }
    
        string I2.Foo() { ... }
    }
    
  2. 例如,如果更新一个接口以更改参数,则使用该接口的代码将更容易更新,而不会破坏其他接口实现。

于 2018-01-11T21:33:03.873 回答