【问题标题】:Do interfaces have any purpose besides achieving polymorphism and multiple inheritance?接口除了实现多态和多继承之外还有什么目的吗?
【发布时间】:2022-02-08 01:51:16
【问题描述】:

我试图了解使用接口有什么好处,以便知道何时以及如何使用它们。互联网上的大多数资源都是相对肤浅的,解释了接口是如何工作的,但现在为什么要使用它们,当我查找名义问题时,我没有得到任何结果告诉我接口的目的是否超出了多态性和多重继承。

我的推理是,如果一个接口只被一个类继承,那它就没有用了,而当一个接口被多个类继承时,除非它用于多态性,否则它没有任何区别,并且唯一实现的东西与扩展不同的是多重继承。

如果我确定他们的目的仅限于此,我会对我的设计决策更有信心,如果我知道了此之外的目的,它将填补我的知识空白。我使用了设计模式标签,因为可能有一种设计模式以一种明显超越单纯多态性或多重继承的方式使用接口。

【问题讨论】:

  • 多重继承的“另一面”是接口提供的契约。例如,List 接口没有提供任何值得由其实现类继承的实现(使多重继承成为一个相当薄的目标)。交易是您将有许多类根据不同的属性表现,但遵守相同的“列表”合同。这样,契约式设计可以为 API 开发人员和 API 调用者/消费者提供可靠的契约,同时允许他们松散耦合。
  • @ernest_k 接口(相对于其他任何可能包含方法的东西)是否有任何东西可以让合同设计变得更容易?我认为契约式设计主要是为了确保遵循封装以防止方法被篡改。
  • 严格来说,没有那么多。接口提供了一种“类型”的契约。按合同设计的范围远不止于此(包括方法签名、异常和各方声明/承担的责任)......无论如何,这就是我的理解。事实是,接口使您能够拥有为您提供多态性的合同(在相同类型的意义上,不同的实现)是按合同设计的有效工具,imo。你读过这个programming to an interface question吗?
  • @ernest_k 谢谢!我开始看到使用接口作为更容易修改的更有条理的代码的工具。也许从简化的角度来看,它们只是关于多态性,但这种只关注功能的观点会忽略设计动机。我喜欢这种针对整个类型而不是单个方法的合同的想法。根据该抽象组织代码似乎是创建接口的一个很好的动机。这个链接很有帮助。

标签: java oop design-patterns


【解决方案1】:

如果一个接口只被一个类继承,那就没用了

我同意,但您可以在Java Interfaces Methodology: Should every class implement an interface? 阅读很多关于此主题的讨论

当一个接口被多个类继承时,除非用于多态性,否则没有区别

我同意,实现一个接口然后通过直接在具体类上调用它的方法来绕过它是愚蠢的。实现接口的目的是调用其抽象方法,这就是多态性。由于多态性是面向对象编程的主要工具,因此您可以更进一步地说,OOP 没有任何区别,除非它用于多态性

实现与扩展唯一不同的是多重继承

不,这些 Java 构造之间的主要区别在于接口实现促进无状态继承,而类扩展促进有状态继承。 Java恰好支持多重无状态继承和单一状态继承。这种二分法可以认为是mistake

接口除了实现多态和多继承之外还有其他用途吗?

在实践中,是的。您可以找到用于其他用途的接口,例如constant interfacesmarker interfaces。这些做法是否可取一直存在争议。

【讨论】:

  • 我没有将此标记为答案,因为它没有对我的主要问题说是或否,但我非常感谢您的澄清,谢谢!
  • 好点。我已经扩展了答案。
【解决方案2】:

假设您说的是language feature(例如Java 中的interface 关键字),而不是general computing term,接口的目的是多态性。

接口等工具可能会被滥用于其他目的,例如:

  • 作为一种交流通用性的方式——这可能会适得其反,因为如果多态性不是设计的目标,那么声明实现接口的类就会做出不必要的承诺来实现它。当通用性最终被破坏时,这可能不再相关,这可能是因为类没有以多态方式使用。

  • 作为记录合同并允许更改类实现的一种方式 - 在 Java 中,这是通过 public/protected 方法实现的,Javadoc 是记录合同的方式。有些语言甚至没有,它们仍然记录合同。当然,这仅在合约以函数调用的形式出现时才有效(与例如 RESTful HTTP API 不同),并且仅在您对文档内容有规则时才有效,例如包边界;您不会希望为每个 class 创建一个 interface,即使您记录了每个课程的合同。

  • 为了从你的接口的消费者物理上隐藏一些东西——这也是关于记录合同,但如果你的类有数据或受保护的方法,并且你想防止你的包之外的任何东西继承,你可以只公开一个界面。但你也可以使用final

接口不是为实现多重继承而设计的;他们宁愿只在对多态有用的范围内促进多重继承;它实际上并不允许您继承任何字段,并且直到最近在 Java 中使用默认方法(因此,不是 设计),甚至是代码。

你会在野外看到只有一个类实现接口的包。这不会使界面无用;未来可能会有更多的实现,事实上,这个包可能希望允许调用者提供他们自己的实现。

【讨论】:

    猜你喜欢
    • 2012-11-12
    • 2020-11-26
    • 2010-10-05
    • 2013-10-22
    • 2012-06-10
    • 2011-11-21
    • 2011-10-07
    • 1970-01-01
    相关资源
    最近更新 更多