Interfaces (interface/abstract class) are not abstractions?
Of late, I have b开发者_开发百科een reading posts which talks about the supposed wrong notion that interfaces are abstractions. One such post is http://blog.ploeh.dk/2010/12/02/InterfacesAreNotAbstractions.aspx
I am a bit confused. If I don't have interfaces (interface/abstract class), then how will I inject my dependencies and mock them?
Also, I have heard people talk about not using interfaces which has just one implementor. Like this blog here - http://simpleprogrammer.com/2010/11/02/back-to-basics-what-is-an-interface/
Now all this, doesn't it violate the principle - Program to an interface and not implementation?
Programming to an interface instead of an implementation is more about using data abstraction and encapsulation.
When we say "interface" in terms of programming to an interface. That kind of interface means the external facing methods and properties of a class. It doesn't have to be a language level interface. (The keyword interface.)
You should be striving to make sure that your code is not dependent on the internal details of other classes.
I'd say I disagree with many of the points in the linked articles:
interfaces are contracts. The contract has two parts - the method signature (purely syntactic) and the documentation.
interfaces are abstractions. I couldn't see an example of LSP violation. The
IRectangle
example is not a good one at all. The same thing can be said aboutSet extends Collection
, where adding duplicates is disallowed. If you are passed aCollection
you might be surprised it disallows duplicates. With theCollection
interfaces this is taken care of by documenting that implementors may add restrictionsLeaky abstractions are inevitable. But this entirely depends on the designer. And btw "interfaces are leaky abstractions" means they are abstractions.
The guys seem to have missed "exposure" to unit-testing. Mock implementations are a very good reason to use an interface (although you can mock concrete classes as well).
A very good example from our current project - initially we has only one DAO implementation - one taking stuff form the database. But later we switched some of the operations to a dedicated search engine. We add another implementation of the DAO, and there we go. So having an interface with one implementation initially paid off.
Btw, initially
SortedSet
had only one implementation in the JDK -TreeSet
. Now it has two. And many more from external libraries.finally, interfaces (as a language construct) are a way to describe a class' functionality with the extra feature of disallowing any implementation slipping in. That is - interfaces are a hard to misuse way of providing abstraction.
That all said, you don't need an interface for everything. But it depends on the concrete case. I, for example, don't use interfaces for helper classes. And a valid point of the articles is the "programming to an interface" does not necessarily include the interface
keyword. The "public interface" of a class is (theoretically) the set of its public methods.
As long as you don't overdo it, I believe you're better off creating an interface.
Here's a use case I frequently have where having only one implementor is (in my opinion) perfectly fine: you have a Swing component, let's say it's a CarComparisonResultsPanel
, which allows the user to see the results of the comparison between cars. As a user of the panel, I'd rather have a CarComparisonResult
interface with just getCarSimilarities()
and getCarDifferences()
than a JPanel implementation that implements those methods as well as dozens of others.
EDIT: To make my "don't over do it" point a bit clearer, these are some examples of overdoing it: interfaces for Factories, Builders, Helper/Utility classes, GUI components that don't add relevant public methods to their parent, ...
The principles behind programming to an interface don't have to be left to interface only situations. When you're designing your interfaces, the general questions you're asking are "Where am I expecting this to be consumed? By whom? And to what purpose?" Questions that should be asked even when creating implementation classes.
It might be that, while designing an interface, you come to the realization that you don't really need to make this an interface, and allowing overloading and inheriting will suffice for testing. As the first article mentioned, if you're consistently ending up with a 1:1 correlation between objects and interfaces with no purpose other than "I'm programming against interfaces," you're just making a mess of your code.
But, that doesn't mean you can't go ahead and design the class as if you were creating an interface/base class for it, with a set of generic methods/properties/fields that provide base functionality and then add other methods/properties/fields more specific to the implementation. Doing so would still, IMO, fall within the principles of programming to an interface. It would, also, certainly leave the door open for you to extract an interface/base class when a clear and definite need arose.
You can have abstraction in two different flavors, which are:
- vertical ( “Is-a” relationship )
- horizontal ( methods )
When programmatically we decide for more generic types instead of more specific types, during the development phase, we bring abstraction to the code, because it doesn't matter at runtime which concrete implementation will be used (e.g. dependency injection, method declaration).
Along these lines, we use interfaces and abstract classes for greater generalization and loose coupling.
Another possibility would be by invoking a method, as the consuming application (client-side) would only use the functionality/service, being the implementation made within another class hidden from it.
精彩评论