【问题标题】:Why should I use an interface when there is only one implementation class?当只有一个实现类时,为什么要使用接口?
【发布时间】:2016-05-18 13:42:14
【问题描述】:

我是编程新手,我正在学习 Java。 我只是想知道当只有一个实现类时为什么要使用接口?

【问题讨论】:

  • 重新打开,因为这个问题比所谓的重复问题要具体得多。
  • 记录在案,如果有人对“所谓的重复”感兴趣,比如我自己:stackoverflow.com/questions/1321122/…

标签: java interface implementation


【解决方案1】:

接口可以由多个类实现。没有规定只有一个类可以实现这些。接口为java提供抽象。

http://www.tutorialspoint.com/java/java_interfaces.htm 您可以从此链接获取有关接口的更多信息

【讨论】:

  • 这是一个“仅链接的答案”,在 StackOverflow 上被认为是错误的形式,因为链接变坏了。问问自己,如果没有链接,答案会有多好。除非你准备好让答案足够独立,否则它应该是一个评论。
  • 我不认为提问者认为您仅限于一个实现类。我想他们更想知道为什么有人会在他们只有一个实现类的情况下拆分接口。
【解决方案2】:

您这样做是为了防止其他人访问您的实现类型。例如,您可以将实现类型隐藏在库中,授予类型包访问权限,并将接口实例返回给库的用户:

// This is what the users of your library know about the class
// that does the work:
public interface SomeInterface {
    void doSomethingUseful();
    void doSomethingElse();
}

// This is the class itself, which is hidden from your clients
class MyImplementation implements SomeInterface {
    private SomeDependency dependency = new SomeDependency();
    public void doSomethingUseful() {
        ...
    }
    public void doSomethingElse() {
        ...
    }
}

您的客户获得这样的对象:

public class MyFactory {
    static SomeInterface make() {
        // MyFactory can see MyImplementation
        return new MyImplementation();
    }
}

当实现使用大量库时,这个技巧变得很有用。您可以有效地将库的接口与其实现分离,这样用户就不必知道您的库内部的依赖关系。

【讨论】:

  • 我看不出给用户一个接口和给用户实现类之间的区别。 “外观和感觉”是一样的......
  • @Nitek:这是一个由此解决的示例,其中 OP 希望将公共方法公开给他不想向最终用户公开的测试:stackoverflow.com/a/6913509/217324
  • @Nitek 这不是关于外观和感觉,而是关于将您图书馆的用户与他们不应该看到的事物隔离开来。
  • 不确定将方法公开以进行测试然后尝试隐藏它们是否是一种好的风格。我知道在某些情况下这可能有意义,但我认为这更像是一种边缘情况,而不是良好的编程风格。
  • 也许值得一提的是,还有很多情况下 YAGNI 是一个很好的默认值...
【解决方案3】:

其中一个原因是为了保持开放/封闭原则,即您的代码应该对扩展开放,但对修改关闭。尽管您现在只有一个实现类,但随着时间的推移,您可能需要另一个不同的实现类。如果您事先将实现提取到接口中,则只需编写另一个实现类,即。您不必修改一段完美运行的代码,消除了引入错误的风险。

【讨论】:

    【解决方案4】:

    它可以让您灵活地在将来添加更多实现,而无需更改引用该接口的客户端代码。

    另一个有用的例子是在需要时在 Java 中模拟多重继承。例如,假设您有一个接口 MyInterface 和一个实现:

    public interface MyInterface {
      void aMethod1();
      void aMethod2();
    }
    
    class MyInterfaceImpl implements MyInterface {
      public void aMethod1() {...}
      public void aMethod2() {...}
    }
    

    你还有一个不相关的类,它有自己的层次结构:

    public class SomeClass extends SomeOtherClass {
     ...
    }
    

    现在您想让SomeClass 的类型为MyInterface,但您还想继承MyInterfaceImpl 中已经存在的所有代码。由于您不能同时扩展SomeOtherClassMyInterfaceImpl,因此您可以实现接口并使用委托:

    public class SomeClass extends SomeOtherClass implements MyInterface {
      private MyInterface myInterface = new MyInterfaceImpl();
    
      public void aMethod1() {
        myInterface.aMethod1();
      }
    
      public void aMethod2() {
        myInterface.aMethod2();
      }
      ...
    }
    

    【讨论】:

      【解决方案5】:

      遵守接口隔离原则。

      创建接口的决定不应基于实现类的数量,而应取决于使用对象的不同方式的数量。使用对象的每种方式都由一个接口表示,由使用它的代码定义。假设您的对象需要存储在内存中,在保持对象有序的集合中。同样的对象也需要存储在一些持久性存储中。

      假设您首先实现持久性。存储系统需要的是持久对象的唯一标识符。您使用 getUniqueId 方法创建一个接口,比如 Storable。然后实现存储。

      然后,您实现该集合。您可以使用方法 compareTo 从接口中的存储对象(如 Comparable)中定义集合需要什么。然后,您可以依赖 Comparable 来实现该集合。

      您要定义的类将实现这两​​个接口。

      如果您定义的类实现了一个接口,则该接口必须代表收集和存储系统的需求。这会导致,例如:

      • 必须使用实现 Storable 的对象来编写集合的单元测试,从而增加一定程度的复杂性。

      • 如果以后需要显示对象,则必须将显示代码所需的方法添加到单个界面中,并修改收集和存储的测试以实现显示所需的方法。

      我在这里谈论对测试代码的影响。如果其他生产级别的对象需要存储而不是显示,则问题会更大。项目越大,不遵守接口隔离原则所产生的问题就会越大。

      【讨论】:

        【解决方案6】:

        我看到这篇文章提出了很多好的观点。还想把我的 2 美分加到这个知识库中。

        接口 鼓励团队环境中的并行开发。可以有 2 个类 A 和 B,A 调用 B 的 API。可以有 2 个开发人员同时在 A 和 B 上工作。当 B 尚未准备好时,A 完全可以通过与 B 的接口集成来实现自己的实现。

        接口是在不同代码层之间建立 API 契约的良好基础。

        最好将关注点与接口处理隐式 API 文档分开。参考一个并确定哪些 API 可供客户端调用非常容易。

        最后,最好在项目中练习使用接口作为标准,而不是在逐个案例基础上使用它(您需要多个实现)。这可确保项目的一致性。

        对于 Java 代码这门艺术来说,接口让它们变得更加美丽 :)

        【讨论】:

          猜你喜欢
          • 2011-11-10
          • 2018-07-19
          • 1970-01-01
          • 1970-01-01
          • 2012-01-18
          • 1970-01-01
          • 1970-01-01
          • 2013-09-22
          • 2013-05-24
          相关资源
          最近更新 更多