【问题标题】:Why is it important which interface method is called?为什么调用哪个接口方法很重要?
【发布时间】:2018-01-11 20:23:20
【问题描述】:

我正在研究接口,并且在某个时候我来到了显式接口实现。在一个教程video at about 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();
    }
}

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

【问题讨论】:

    标签: c# oop interface explicit-interface


    【解决方案1】:

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

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

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

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

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

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

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

    【讨论】:

      【解决方案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.
      }
      

      【讨论】:

        【解决方案3】:

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

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

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

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

        【讨论】:

        • “我相信 C# 将其视为模棱两可的引用,而不仅仅是对两者使用相同的实现” - c# 确实对两者使用相同的实现......模棱两可纯粹是在编写代码的人的眼睛。
        • 此外,如果您在接口上的两个方法确实具有不同的返回类型,那么编译器会抱怨,因为您没有实现其中一个接口(因为返回类型错误的实现无法匹配并且您不能有两种仅在返回类型上有所不同的方法)。
        猜你喜欢
        • 2019-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-16
        • 1970-01-01
        • 2017-09-03
        • 1970-01-01
        相关资源
        最近更新 更多