Java 接口方法论:每个类都应该实现一个接口吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2659366/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 22:15:25  来源:igfitidea点击:

Java Interfaces Methodology: Should every class implement an interface?

javainterface

提问by Amir Rachum

I've been programming in Java for a few courses in the University and I have the following question:

我在大学的几门课程中一直在用 Java 编程,我有以下问题:

Is it methodologically accepted that every class should implement an interface? Is it considered bad practice not to do so? Can you describe a situation where it's not a good idea to use interfaces?

每个类都应该实现一个接口在方法论上是否被接受?不这样做是否被认为是不好的做法?你能描述一下使用接口不是一个好主意的情况吗?

Edit:Personally, I like the notion of using Interfaces for everything as a methodology and habit, even if it's not clearly beneficial. Eclipse automatically created a class file with all the methods, so it doesn't waste any time anyway.

编辑:就我个人而言,我喜欢将接口作为一种方法论和习惯用于一切事物的概念,即使它显然没有好处。Eclipse 自动创建了一个包含所有方法的类文件,因此无论如何都不会浪费任何时间。

回答by Philippe Grenet

You don't need to create an interface if you are not going to use it.

如果您不打算使用它,则不需要创建接口。

Typically you need an interface when:

通常在以下情况下您需要一个接口:

  • Your program will provide several implementations for your component. For example, a default implementation which is part of your code, and a mock implementation which is used in a JUnit test. Some tools automate creating a mock implementation, like for instance EasyMock.
  • You want to use dependency injection for this class, with a framework such as Spring or the JBoss Micro-Container. In this case it is a good idea to specify the dependencies from one class with other classes using an interface.
  • 您的程序将为您的组件提供多种实现。例如,作为代码一部分的默认实现,以及在 JUnit 测试中使用的模拟实现。一些工具会自动创建模拟实现,例如 EasyMock。
  • 您想对此类使用依赖注入,使用 Spring 或 JBoss Micro-Container 等框架。在这种情况下,最好使用接口指定一个类与其他类的依赖关系。

回答by Petar Minchev

Following the YAGNIprinciple a class should implement an interface if you really need it. Otherwise what do you gain from it?

遵循YAGNI原则,如果您真的需要,一个类应该实现一个接口。否则你从中得到什么?

Edit: Interfaces provide a sort of abstraction. They are particularly useful if you want to interchange between different implementations(many classes implementing the same interface). If it is just a single class, then there is no gain.

编辑:接口提供了一种抽象。如果您想在不同的实现(实现相同接口的许多类)之间进行交换,它们特别有用。如果只是一个班级,那就没有什么收获了。

回答by richj

Every class does implement an interface (i.e. contract) insofar as it provides a non-private API. Whether you should choose to represent the interface separately as a Java interface depends on whether the implementation is "a concept that varies".

每个类都实现了一个接口(即契约),因为它提供了一个非私有 API。是否应该选择将接口单独表示为 Java 接口取决于实现是否是“一个变化的概念”。

If you are absolutely certain that there is only one reasonable implementation then there is no need for an interface. Otherwise an interface will allow you to change the implementation without changing client code.

如果您绝对确定只有一个合理的实现,那么就不需要接口。否则,接口将允许您在不更改客户端代码的情况下更改实现。

Some people will shout "YAGNI", assuming that you have complete control over changing the code should you discover a new requirement later on. Other people will be justly afraid that they will need to change the unchangeable - a published API.

有些人会大喊“YAGNI”,假设您在以后发现新需求时可以完全控制更改代码。其他人会担心他们需要更改不可更改的 - 已发布的 API。

If you don't implement an interface (and use some kind of factory for object creation) then certain kinds of changes will force you to break the Open-Closed Principle. In some situations this is commercially acceptable, in others it isn't.

如果您不实现接口(并使用某种工厂来创建对象),那么某些类型的更改将迫使您打破开闭原则。在某些情况下,这在商业上是可以接受的,而在其他情况下则不是。

Can you describe a situation where it's not a good idea to use interfaces?

你能描述一下使用接口不是一个好主意的情况吗?

In some languages (e.g. C++, C#, but not Java) you can get a performance benefit if your class contains no virtual methods.

在某些语言(例如 C++、C#,但不是 Java)中,如果您的类不包含虚拟方法,您可以获得性能优势。

In small programs, or applications without published APIs, then you might see a small cost to maintaining separate interfaces.

在没有发布 API 的小程序或应用程序中,您可能会看到维护单独接口的成本很小。

If you see a significant increase in complexity due to separating interface and implementation then you are probably not using interfaces as contracts. Interfaces reduce complexity. From the consumer's perspective, components become commodities that fulfil the terms of a contract instead of entities that have sophisticated implementation details in their own right.

如果您看到由于分离接口和实现而导致复杂性显着增加,那么您可能没有将接口用作契约。接口降低了复杂性。从消费者的角度来看,组件成为履行合同条款的商品,而不是拥有复杂实现细节的实体。

回答by Kaleb Brasee

No, it's not necessary for every class to implement an interface. Use interfaces only if they make your code cleaner and easier to write.

不,并不是每个类都需要实现一个接口。仅当接口使您的代码更清晰、更易于编写时才使用接口。

If your program has no current need for to have more than 1 implementation for a given class, then you don't need an interface. For example, in a simple chess program I wrote, I only need 1 type of Board object. A chess board is a chess board is a chess board. Making a Board interface and implementing that would have just required more code to write and maintain.

如果您的程序当前不需要为给定类提供 1 个以上的实现,那么您就不需要接口。例如,在我编写的一个简单的国际象棋程序中,我只需要一种类型的 Board 对象。棋盘就是棋盘就是棋盘。制作一个 Board 接口并实现它只需要更多的代码来编写和维护。

It's so easy to switch to an interface if you eventually need it.

如果您最终需要,切换到一个界面非常容易。

回答by Will Iverson

Creating an interface for every class is unnecessary. Some commonly cited reasons include mocking (unneeded with modern mocking frameworks like Mockito) and for dependency injection (e.g. Spring, also unneeded in modern implementations).

没有必要为每个类创建一个接口。一些常见的原因包括模拟(现代模拟框架如 Mockito 不需要)和依赖注入(例如 Spring,在现代实现中也不需要)。

Create an interface if you need one, especially to formally document public interfaces. There are a couple of nifty edge cases (e.g. marker interfaces).

如果需要,请创建一个接口,尤其是要正式记录公共接口。有几个漂亮的边缘情况(例如标记界面)。

For what it's worth, on a recent project we used interfaces for everything (both DI and mocking were cited as reasons) and it turned out to be a complete waste and added a lot of complexity - it was just as easy to add an interface when actually needed to mock something out in the rare cases it was needed. In the end, I'm sure someone will wind up going in and deleting all of the extraneous interfaces some weekend.

值得一提的是,在最近的一个项目中,我们对所有东西都使用了接口(DI 和模拟都被列为原因),结果证明这是一种完全的浪费并增加了很多复杂性 - 添加接口同样容易实际上需要在极少数情况下模拟一些东西。最后,我相信有人会在某个周末进入并删除所有无关的接口。

I do notice that C programmers first moving to Java tend to like lots of interfaces ("it's like headers"). The current version of Eclipse supports this, by allowing control-click navigation to generate a pop-up asking for interface or implementation.

我确实注意到,最初转向 Java 的 C 程序员往往喜欢很多接口(“它就像标头”)。当前版本的 Eclipse 支持这一点,通过允许控制单击导航生成一个弹出窗口,询问接口或实现。

回答by Otávio Décio

I've found that it is beneficial to define the public methods of a class in a corresponding interface and when defining references to other classes strictly use an interface reference. This allows for easy inversion of control, and it also facilitates unit testing with mocking and stubbing. It also gives you the liberty of replacing the implementation with some other class that implements that interface, so if you are into TDD it may make things easier (or more contrived if you are a critic of TDD)

我发现在相应的接口中定义类的公共方法并且在定义对其他类的引用时严格使用接口引用是有益的。这允许轻松反转控制,并且还有助于使用模拟和存根进行单元测试。它还使您可以自由地将实现替换为实现该接口的其他类,因此如果您使用 TDD,它可能会使事情变得更容易(如果您是 TDD 的批评者,则可能会更加做作)

回答by Micha? Mech

Interfaces are the way to get an polymorphism. So if You have only one implementation, one class of particularly type, You don't need an interface.

接口是获得多态性的方式。因此,如果您只有一个实现,一个特定类型的类,则不需要接口。

回答by Julien Silland

To answer the OP's question in a very blunt way: no, not all classes need to implement an interface. Like for all design questions, this boils down to one's best judgment. Here are a few rule of thumbs I normally follow:

以非常直率的方式回答 OP 的问题:不,并非所有类都需要实现接口。与所有设计问题一样,这归结为一个人的最佳判断。以下是我通常遵循的一些经验法则:

  • Purely functional objects probably don't need to (e.g. Pattern, CharMatcher – even though the latter does implement Predicate, it is secondary to its core function)
  • Pure data holders probably don't need to (e.g. LogRecord, Locale)
  • If you canenvision a different implementation of a given functionality (say, in-memory Cache vs. disk-based Cache), try to isolate the functionality into an interface. But don't go too far trying to predict the future either.
  • For testing purposes, it's very convenient when classes that do I/O or start threads are easily mockable, so that users don't pay a penalty when running their tests.
  • There's nothing worse than a interface that leaks its underlying implementation. Pay attention where you draw the line and make sure your interface's Javadoc is neutral in that way. If it's not, you probably don't need an interface.
  • Generally speaking, it is preferable for classes meant for public consumption outside your package/project to implement interfaces so that your users are less coupled to your implementation du jour.
  • 纯函数对象可能不需要(例如 Pattern、CharMatcher——尽管后者确实实现了 Predicate,但它的核心功能是次要的)
  • 纯数据持有者可能不需要(例如 LogRecord、Locale)
  • 如果您可以设想给定功能的不同实现(例如,内存缓存与基于磁盘的缓存),请尝试将功能隔离到接口中。但也不要试图预测未来。
  • 出于测试目的,当执行 I/O 或启动线程的类很容易模拟时,这是非常方便的,这样用户在运行测试时就不会付出代价。
  • 没有什么比泄漏其底层实现的接口更糟糕的了。注意你画线的地方,并确保你的界面的 Javadoc 以这种方式是中立的。如果不是,您可能不需要接口。
  • 一般来说,最好让用于包/项目之外的公共使用的类实现接口,这样您的用户就可以减少与您的日常实现的耦合。

Note that you can probably find counter-examples for each of the bullets in that list. Interfaces are very powerful, so they need to be used and created with care, especially if you're providing external APIs (watch this videoto convince yourself). If you're too quick in putting an interface in front of everything, you'll probably end up leaking your single implementation, and you are only making things more complicated for the people following you. If you don't use them enough, you might end up with a codebase that is equally hard to maintain because everything is statically bound and very hard to change. The non-exhaustive list above is where I try to draw the line.

请注意,您可能会为该列表中的每个项目符号找到反例。接口非常强大,因此需要谨慎使用和创建它们,尤其是在您提供外部 API 的情况下(观看此视频以说服自己)。如果您太快地将接口放在所有内容的前面,您可能最终会泄露您的单个实现,并且只会让跟随您的人的事情变得更加复杂。如果您没有充分使用它们,您最终可能会得到一个同样难以维护的代码库,因为一切都是静态绑定的并且很难更改。上面的非详尽列表是我试图划清界限的地方。

回答by Ha.

If you use Service Provider Interface pattern in your application interfaces are harder to extend than abstract classes. If you add method to interface, all service providers must be rewritten. But if you add non-abstract method to the abstract class, none of the service providers must be rewritten.

如果您在应用程序中使用服务提供者接口模式,则接口比抽象类更难扩展。如果向接口添加方法,则必须重写所有服务提供者。但是,如果在抽象类中添加非抽象方法,则不必重写任何服务提供者。

Interfaces also make programming harder if only small part of the interface methods usually have meaningfull implementation.

如果只有一小部分接口方法通常具有有意义的实现,则接口也会使编程更加困难。

回答by Avi

A good way of learning what are considered good methodologies, especially when it comes to code structure design, is to look at freely available code. With Java, the obvious example is to take a look at the JDK system libraries.

学习什么被认为是好的方法论的一个好方法,特别是在涉及代码结构设计时,是查看免费可用的代码。对于 Java,最明显的例子是查看JDK 系统库

You will find many examples of classes that do not implement any interfaces, or that are meant to be used directly, such as java.util.StringTokenizer.

您会发现许多未实现任何接口或打算直接使用的类的示例,例如 java.util.StringTokenizer。