简体   繁体   English

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

[英]Java Interfaces Methodology: Should every class implement an interface?

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使用所有方法自动创建了一个类文件,因此无论如何都不会浪费时间。

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. 例如,默认实现是代码的一部分,而模拟实现是在JUnit测试中使用的。 Some tools automate creating a mock implementation, like for instance EasyMock. 一些工具会自动创建模拟实现,例如EasyMock。
  • You want to use dependency injection for this class, with a framework such as Spring or the JBoss Micro-Container. 您想通过诸如Spring或JBoss Micro-Container之类的框架对此类使用依赖注入。 In this case it is a good idea to specify the dependencies from one class with other classes using an interface. 在这种情况下,最好使用一个接口指定一个类与其他类的依赖关系。

Following the YAGNI principle a class should implement an interface if you really need it. 遵循YAGNI原则,如果您确实需要,则类应实现接口。 Otherwise what do you gain from it? 否则,您将从中获得什么?

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. 如果只是一个班级,那么就没有收获。

Every class does implement an interface (ie contract) insofar as it provides a non-private API. 每个类都提供一个非私有API,但确实实现了一个接口(即合同)。 Whether you should choose to represent the interface separately as a Java interface depends on whether the implementation is "a concept that varies". 是否选择将接口表示为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. 假设您以后对新的要求有完全的控制权,那么有些人会大喊“ YAGNI”。 Other people will be justly afraid that they will need to change the unchangeable - a published API. 其他人会公平地担心,他们将需要更改不变的-已发布的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 (eg 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. 从消费者的角度来看,组件成为满足合同条款的商品,而不是本身具有复杂实施细节的实体。

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. 例如,在我编写的一个简单的国际象棋程序中,我只需要一种类型的Board对象。 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. 制作一个Board接口并实现该接口仅需要编写和维护更多代码。

It's so easy to switch to an interface if you eventually need it. 如果最终需要它,那么切换到界面非常容易。

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 (eg 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 (eg 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. 出于其价值,在最近的项目中,我们对所有内容都使用了接口(都引用了DI和模拟作为原因),事实证明这完全是浪费,而且增加了很多复杂性-在添加接口时就很容易实际上在少数情况下需要模拟某些东西。 In the end, I'm sure someone will wind up going in and deleting all of the extraneous interfaces some weekend. 最后,我确定某个周末有人会进入并删除所有无关的接口。

I do notice that C programmers first moving to Java tend to like lots of interfaces ("it's like headers"). 我确实注意到,刚开始使用Java的C程序员倾向于喜欢很多接口(“就像标头”)。 The current version of Eclipse supports this, by allowing control-click navigation to generate a pop-up asking for interface or implementation. Eclipse的当前版本通过允许控制单击导航来生成弹出式窗口来询问接口或实现来支持此功能。

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的批评者,则可能会更加作弊)

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. 因此,如果您只有一个实现,一个特别类型的类,则不需要接口。

To answer the OP's question in a very blunt way: no, not all classes need to implement an interface. 要以一种非常直截了当的方式回答OP的问题:不,并非所有类都需要实现一个接口。 Like for all design questions, this boils down to one's best judgment. 像所有设计问题一样,这归结为一个人的最佳判断。 Here are a few rule of thumbs I normally follow: 我通常会遵循一些经验法则:

  • Purely functional objects probably don't need to (eg Pattern, CharMatcher – even though the latter does implement Predicate, it is secondary to its core function) 纯功能对象可能不需要(例如Pattern,CharMatcher –尽管后者确实实现了谓词,但它仅次于其核心功能)
  • Pure data holders probably don't need to (eg LogRecord, Locale) 纯数据持有人可能不需要(例如LogRecord,Locale)
  • If you can envision 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. 出于测试目的,当可以轻松模拟执行I / O或启动线程的类时,这非常方便,从而使用户在运行测试时无需付出任何代价。
  • 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. 注意划界线的位置,并确保接口的Javadoc以这种方式保持中立。 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. 一般而言,对于包/项目外部的供公众使用的类,最好实现接口,以使用户减少与实现时的耦合。

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 video to convince yourself). 接口非常强大,因此需要谨慎使用和创建接口,尤其是在您提供外部API的情况下(观看此视频以说服自己)。 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. 上面非详尽的清单是我尝试画线的地方。

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。

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. 如果只有一小部分接口方法通常具有有意义的实现,则接口也会使编程更加困难。

When I design a new system from scratch I use a component oriented approach, each component (10 or more classes) provide an interface, this allows me (sometimes) to reuse them. 当我从头开始设计新系统时,我使用面向组件的方法,每个组件(10个或更多类)都提供一个接口,这使我(有时)可以重用它们。

  • When designing a Tool (Or a simple system) I think this must not necessarily be an extensible framework I introduce interfaces when I need a second implementation as an option. 在设计工具(或简单系统)时,我认为这不一定是可扩展的框架,当我需要第二种实现作为选项时,我会介绍接口。

  • I saw some products which exposed nearly every functionality by an interface, it took simply too much time to understand unnecessary complexity. 我看到一些产品通过接口公开了几乎所有功能,花了太多时间来了解不必要的复杂性。

An interface is like a contract between a service provider (server) and the user of such a service (client). 接口就像服务提供商(服务器)和该服务的用户(客户端)之间的合同。

  • If we are developing a Webservice and we are exposing the rest routes via controller classes, controller classes can implement interfaces and those interfaces act as the agreement between web service and the other applications which use this web service. 如果我们正在开发Web服务,并且通过控制器类公开其余路由,则控制器类可以实现接口,并且这些接口充当Web服务与使用此Web服务的其他应用程序之间的协议。
  • Java interfaces like Serializable , Clonnable and Remote used to indicate something to compiler or JVM.When JVM sees a class that implement these interfaces, it performs some operation on the to support Serialization, cloning or Remote Method Invocation. Java接口(例如SerializableClonnableRemote)用于指示编译器或JVM。当JVM看到实现这些接口的类时,它将在上执行一些操作以支持序列化,克隆或Remote Method Invocation。 If your class needs these features, then you will have to implement these interfaces. 如果您的班级需要这些功能,则必须实现这些接口。

Using Interface is about to make your application framework resilient to change. 使用接口将使您的应用程序框架具有适应变化的能力。 Since as I mentioned here ( Multiple Inheritance Debates II: according to Stroustrup ) multiple inheritance was cancelled in java and c# which I regret, one should always use Interface because you never know what the future will be. 因为正如我在这里提到的( 多重继承辩论II:根据Stroustrup所述 ),在Java和c#中取消了多重继承,对此我感到遗憾,所以应该始终使用Interface,因为您永远都不知道将来会是什么样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM