2

在高层次上,我对接口的了解是这样的:

  • 他们声明方法但不实现它们
  • 任何实现接口的类都必须实现其声明的所有方法

对我来说,这立即暴露了两个主要问题:

  • 因为任何实现类都必须实现其所有方法,这实际上意味着接口一旦使用就不能更改。在接口中添加或删除方法意味着更改使用它的每个类。答案可能正是如此;他们不应该改变,但是我们如何保证我们的设计是稳定的呢?

  • 假设实现接口的类实际上在它们的实现中使用相同的逻辑。这是代码重复,难以维护。这不是基类和继承的重点吗?

我有这个想法是因为我认为我已经很好地掌握了它。我认为接口作为类的“螺栓连接”或“插件”,赋予它一些额外的功能,因此该功能与该类型的类无关,例如,接口可能定义计算表面积的方法,但是很多东西都有一个表面积,而不仅仅是“形状”或“建筑”,所以创建一个“螺栓固定”(接口)来计算表面积似乎是合理的,但很可能该接口的每个实现都将是一样,那么好处在哪里呢?这是一个公平的评论吗?我确信它们提供了很大的好处,我只是还没有看到。

4

4 回答 4

2

在其他答案中,重要的是要注意接口通常应该封装尽可能少的逻辑来执行相关操作。一个非常简单的例子:

public IVehicle 
{ 
    void Start();
    void Stop();
    void Accelerate();
    void Decelerate();
    void TurnLeft();
    void TurnRight();
    void Reverse();
}

public interface IAeronauticVehicle : IVehicle
{
    void TakeOff();
    void Land();
    void Ascend();
    void Descend();
}

然后你可以有

public class Car : IVehicle
{
    // ... implementation ...
}

public class Airplane : IAeronauticVehicle
{
    // ... similar IVehicle implementation
    // ... and then the IAeronauticVehicle implementation

    // You could even nullify certain IVehicle methods that don't apply:
    public void Reverse() 
    {
        throw new NotSupportedException();
    }
}

这是一个非常人为的示例,但它说明了您的 IVehicle 接口不需要关注可能仅适用于 IAeronauticVehicle 实现的扩展属性或方法。您可以稍后添加。通过这样做,您可以扩展您的 Airplane 类和任何使用 IAeronauticVehicle 的代码的功能,而无需更改 IVehicle 定义的基本合同

一个典型的例子是 IEnumerable 接口,它只定义了一个方法GetEnumerator。任何类,无论目的如何,如果它打算返回一组可枚举的项,都可以实现这个接口。这样一来,这个类就可以在任何支持 IEnumerable 的地方立即可用。使用您的 IEnumerable 实现的代码并不关心您的类上的任何其他方法,例如您的类定义的任何FetchRecordsFromDatabase()其他方法。ValidateInput()

接口不应该是包罗万象的,因此必须(几乎)永远不会出现必须更改接口的问题。

于 2013-11-13T09:31:25.143 回答
1

对于第一个问题- 接口是为您的系统提供松散耦合的手段。一个可能有帮助的例子是 HTTP 协议。它是一个允许设备相互通信的接口——但这些设备有时没有任何共同之处。您可能拥有 PC、笔记本电脑、平板电脑、智能手机、智能电视、各种运行桌面 Windows、Linux、Mac、任何移动操作系统、嵌入式操作系统等的设备。尽管它们完全不同,但它们共享一个界面,并且可以轻松地相互交谈。

另一个例子——迭代器模式。您当然已经使用了多种数据结构,并且枚举它们的冲动已经上升。迭代器是一个接口,允许您在数组、链表、队列、堆栈上使用相同的代码。因此,如果您出于某种原因需要更改您的收藏,您可以在不破坏世界另一端的项目的情况下这样做。请注意,我刚才提到的集合以不同的方式实现,并且不共享任何代码。

对于第二个问题- 如果您的类真的以相同的方式实现单个接口,那么您没有理由不使用实现该接口的基类。例如,考虑从 .NET 中挑选的以下层次结构:

interface IEnumerable
class Collection : IEnumerable
class ObservableCollection: Collection
class MailAddressCollection: Collection
class KeyedCollection: Collection
... about 40 other children of Collection

(为清楚起见省略了一些细节)

如您所见,需要相同接口实现的派生类是从一个基类派生的,而不是直接从接口派生的,因此不会重复任何代码。

于 2013-11-13T08:41:14.520 回答
1

至于你的第一个问题,这是完全有道理的。如果类实现了一个接口并且接口发生了变化,那么您必须编辑所有这些。否则,它们不会忠实于接口,这意味着依赖于它们实现接口的类会中断。

接口是契约,实现它们的类承诺它们实现某些功能的其他类。如果他们不这样做,那么首先拥有界面的全部意义就消失了。

于 2013-11-13T09:03:49.060 回答
0

拥有多个实现单个接口的类为您提供了一种使用单一方法操作来自这些不同类的实例化对象的好方法。只需通过他们实现的接口声明那些。而不是为每个类编写不同的方法。这是我头上的第一个好处;)

于 2013-11-13T08:38:30.187 回答