When should I use an interface in java? [closed]
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this questionA good example of when exactly to use interfaces specifically in Java would be ideal and any specific rul开发者_如何学Pythonings that apply.
A good place to look at would be the collections framework.
java.util.List //interface
java.util.ArrayList //Concrete class
java.util.LinkedList //Concrete class
So you can write code like this:
List l = new ArrayList();
l.add(..)
//do something else.
If in future you want to change the implementation with say LinkedList
or you own AwesomeList which implements List
interface, all you have to do is change the very first line to:
List l = new MyAwesomeList();
or
List l = new LinkedList();
The rest of the code would follow through.
Use interfaces to define an application programming contract (blueprint, interface) which "3rd-party" vendors have to fully adhere and implement. This way the endusers can just code against the API contract and easily switch of the concrete implementation "under the hoods" without changing the code.
The JDBC API is an excellent example. It exist of almost only interfaces. The concrete implementations are provided as "JDBC drivers". This enables you to write all the JDBC code independent of the database (DB) vendor. You can just change the JDBC driver without changing any line of Java code (except of any hardcoded DB-specific SQL code) whenever you'd like to switch of DB vendor.
Another example is the Java EE API, it also contains pretty much interfaces and abstract classes. The concrete implementations are provided as "Java EE application servers", "Servletcontainers", etc, such as Sun Glassfish, Apache Tomcat, etc. This enables you to deploy the webapplication (WAR) to whatever Java web server you like.
Interfaces are needed where you expect volatility in your program, points at which you anticipate change, points where your design needs to bend.
Implementation is fragile in this sense: it breaks quite easily. This is why subclassing isn't always the best solution, just as long-winded methods that implement some complicated behavior all by themselves are generally a bad idea.
Interfaces are more flexible and can deal with a lot more stress on the design of your program than implementation.
By introducing interfaces into your program, you really introduce points of variation at which you can plug in different implementations for that interface. Interfaces' primary purpose is abstraction, decoupling the "what" from the "how".
One important rule to keep in mind for safely doing so is the Liskov Substitution Principle [UncleBob, Wikipedia]. While a compiler in a language like Java will make sure that syntactically everything is in order (right number of parameters, types, ...), LSP deals with the semantics. In short, LSP says that every implementation of an interface must (also) behave itself correctly to be truly substitutable as described above.
From oracle documentation page
Consider using interfaces if :
- You expect that unrelated classes would implement your interface. For example,many unrelated objects can implement Serializable interface.
- You want to specify the behaviour of a particular data type, but not concerned about who implements its behaviour.
- You want to take advantage of multiple inheritance of type.
Have a look at related SE questions with code examples which have good answers already.
Is there more to an interface than having the correct methods
What is the difference between an interface and abstract class?
How should I have explained the difference between an Interface and an Abstract class?
Interfaces are used when you need multiple implementations of the same behavior. Here is an example of an interface that objects could implement to show that they all can be serialized to XML.
public interface Xmlizable
{
public String toXML();
}
then you can just pass around "Xmlizable" interfaces into methods that only care about that one interface.
Have a look at JDK collection tutorial at link text. Think about Collections. What comes to your mind? It could be ordered or it may not be ordered and it may have duplicates or not.
So Collection is an interface with List (ordered) and Set (unordered) as sub interfaces. Now there are many questions with Lists, should it be synchronised/or not, should it be a linked list or not etc. Each "behaviour" will have its own interfaces/abstract classes.
Abstract classes are needed when you want to specify "some" behaviour in collections. For example all collections (sets/lists etc) can have a "toString" representation which is just iterate over the elements (ordered/or not) and stringify them. That behaviour can be present in "AbstractCollection" etc.
If you follow the hierarchy of JDK collections, it is an excellent place to learn about interfaces and abstract classes :)
Try to understand Strategy Design Pattern
This answer is essentially the same as coolest_head's, just a bit more explicit in conveying the usefulness.
As coolest_head explains, interfaces are useful when you may want to switch around the possible subcomponents of your program in the future. They also allow you to separate concerns of various parts of your program's structure more easily since with interfaces you can ensure that certain non-related classes etc. just aren't visible to other parts of the program.
As an example, lets assume that you want to read arbitrary data and print it, like so:
SomeReader someReader = new SomeReader();
String data = someReader.readLine();
System.out.println(data);
Nothing fancy here, right? But, while this example is simple, it's already tied to the SomeReader
class which means that all the changes you make to that class must be propagated to the class where you're using the class - especially if you refactor some inner parts! Instead, you want to do this
IMyReader reader = new SomeReader();
System.out.println(reader.readLine());
You're almost there - now the printing code doesn't care about the specific implementation anymore, only about the parts which are exposed by the interface. This is usually enough because now you can just switch around that one new
statement and you get new implementations and whatever which still work as expected (as long as the interface's contract is respected among the implementing classes!). This is especially handy when you end up using that one specific object multiple times - here I'm using it just once but really, if you're working with for example lists, how many operations you usually do the same list?
So, to really blow this example out of proportions, here's what your code may end up looking like
public class RowPrinter {
private final IMyReader reader;
public RowPrinter(IMyReader reader) {
this.reader = reader;
}
public void print() {
IMyReader reader = getReader();
System.out.println(reader.readLine());
}
protected IMyReader getReader() {
return reader;
}
}
Notice that part with the constructor? That's inversion of control and let me just tell you, that's a cool piece of software engineering right there. I can speak from experience it helps you with a lot of hassle, whether it's switching from database product to another or making certain parts of code thread safe. Or maybe you just want to add a layer of logging to some class, easily doable with a wrapping decorator which happens to implement the same interface as the wrapped class. And this is just the beginning.
Interfaces bring lots of benefits which usually aren't that obvious from simple examples although the simple examples do get you going properly. While interfaces in Java are a language construct, they're actually more of a programming paradigm than just a feature of a single language, in some languages emulating interfaces truly is beneficial if you figure out the correct way to do it.
Basically, you can choose between interfaces and abstract classes when you need to "leave out" some implementation details. The interface is usually the better choice, as client classes can implement any amount of interfaces, but they can only one have one superclass ("inheritance is a scarce resource", as they put it).
Why would you want either an abstract class or an interface? Because sometimes, when you write an algorithm you don't care how a specific sub-step of it is done, just that it is done according to some kind of contract. An example would be the Collections API, with List being an interface - usually, when you use a List
, you don't really care if it's saving stuff in an array, or in a linked list of nodes, or in some other kind of way. As long as it stores the stuff you put in it in the order you put them there, you're happy.
Then we have AbstractList
: An abstract class implementing List
, which provides implementation of almost everything a fully-fledged List
needs - to create your own List
implementation, all you have to do is extend AbstractList
and fill in a few methods. This is a prime example of when an abstract class is a good choice - when you want to provide an almost-complete implementation of something, which only is lacking a few gaps which needs to be filled in by the client code.
Hint: If you make an abstract class containing only abstract methods, you should probably make an interface of it.
Interfaces in Remote communication:
Interfaces can also be used to define an agreed upon "protocol" for communicating between different portions of the system, possibly through remote calls. So the interface only defines what can be called, with what parameters, and what will be returned after the call. The client uses the interface and the server implements the concrete actual code for example.
Side Note:
In Java you can only inherent (extend) from one class, but you can implement more than one interface, so sometimes you will have to use interfaces when you need that sort of multiple inheritance and when you decide not to use composition over inheritance.
A basic principle of OOP is information hiding: hide the implementation details, and show only a description of the basic services to the caller.
Java has to constructs for this goal: interfaces and abstract classes. You can define an interface, and write your code, that it only depends on the interface by calling the "available methods" defined in it.
Information hiding is usable both for reading external classes (external in a sense that it comes outside the module you are writing) - this way you can define what methods you need, and there is no need to infer its concrete implementation type - , or when defining a data type usable outside your classes - a typical example for this is e.g. the Collection API or J2EE, as other already mentioned.
Both interfaces and abstract classes provide these details - but there are two major differences: interfaces support multiple inheritance, while abstract classes can hold a base implementation. To maximize their efficiency, when defining an interface, you should also define an abstract class with a meaningful default implementation. If the user of the interface does not need to extend any other class, it can extend this abstract class, otherwise it needs to implement all methods from the interface. On the other hand make sure not to read this abstract class directly, the interface should be enough as abstraction.
Use interfaces whenever you plan to replace an implementation class by another class at some point of development.
I also would recommend to use interface backends for all classes in inheritance relationships at least in more serious projects: Unfortunately I don't have the link anymore but a developer of the language Java once said, that including Class-Inheritance was the biggest mistake in designing the language.
The arguments are quite good: Using proper design, it is always possible to replace class inheritance by interface inheritance and you gain a lot concerning code maintainance. It is also easier to preserve natural type relations (like e.g. from geometry ("a square is a rectangle"-stuff) than with class inheritance.
精彩评论