tags:

views:

386

answers:

8

I want to solidify my understanding of the "coding to interface" concept. As I understand it, one creates interfaces to delineate expected functionality, and then implements these "contracts" in concrete classes. To use the interface one can simply call the methods on an instance of the concrete class.

The obvious benefit is knowing of the functionality provided by the concrete class, irrespective of its specific implementation.

Based on the above:

  1. Are there any fallacies in my understanding of "coding to interfaces"?
  2. Are there any benefits of coding to interfaces that I missed?

Thanks.

+8  A: 

Just one possible correction:

To use the interface one can simply call the methods on an instance of the concrete class.

One would call the methods on a reference of the type interface, which happens to use the concrete class as implementation:

List<String> l = new ArrayList<String>();
l.add("foo");
l.add("bar");

If you decided to switch to another List implementation, the client code works without change:

List<String> l = new LinkedList<String>();

This is especially useful for hiding implementation details, auto generating proxies, etc.

You'll find that frameworks like Spring and Guice encourage programming to an interface. It's the basis for ideas like aspect-oriented programming, auto generated proxies for transaction management, etc.

duffymo
I assume ArrayList implements the List class ? Not sure what language you are providing an example of. I suppose you could sayList l = new SomeOtherList(); ?
JonH
It's Java - List is an interface implemented by ArrayList. Yes, you could have that reference point to a new type of List if you wished.
duffymo
+1 for telling us what the list is. It helps because a lot of folks aren't java developers (me being one). So when I saw List l = new ArrayList() I thought wait a minute List expects <T> where T is a type (in C# that is). So I thought how is he assigning an ArrayList (Which could also potentially be C#) to a list class. Again thank you for pointing that out.
JonH
Time to hit the javadocs for the java.util package a bit harder. I deliberately didn't include generics, but I'll add them if you think it makes the argument clearer.
duffymo
@JonH - actually <T> refers to generics, which isn't terribly relevant to what duffymo is pointing out here, and is optional (though recommended) in Java anyway. duffymo's point is that List is an interface, and when you're dealing with a list, it's best to treat it as a plain old List so that you don't care which implementation it uses. ArrayList is a concrete class that implements List.
Dan
@Dan sorry for the vocab I meant generics which could include a User defined data type or a primitive. I understood duffymo I was just making a comment so that a beginner could see that an ArrayList was just a form of a list. To the seasoned developer this is very clear, to someone quite new to interfaces or programming in general it helps to state that the List is an interface and the array list simply uses that interface. For that reason, SomeOtherList() mentioned in the first comment could potentially be another concrete implementation of the List class. Thanks again +1.
JonH
+1  A: 

You didn't list the part about how you get an implementation of the interface, which is important. If you explicitly instantiate the implementing class with a constructor then your code is tied to that implementation. You can use a factory to get an instance for you but then you're as tied to the factory as you were before to the implementing class. Your third alternative is to use dependency injection, which is having a factory plug the implementing object into the object that uses it, in which case you escape having the class that uses the object being tied to the implementing class or to a factory.

Nathan Hughes
+4  A: 

The main advantage is that the use of an interface loosely couples a class with it's dependencies. You can then change a class, or implement a new concrete interface implementation without ever having to change the classes which depend on it.

Paul Creasey
+2  A: 

The aim of coding against interfaces is to decouple your code from the concrete implementation in use. That is, your code will not make assumptions about the concrete type, only the interface. Consequently, the concrete implementation can be exchanged without needing to adjust your code.

meriton
A: 

I think you may have hinted at this, but I believe one of the biggest benefits of coding to an interface is that you are breaking dependency on concrete implementation. You can achieve loose coupling and make it easier to switch out specific implementations without changing much code. If you are just learning, I would take a look at various design patterns and how they solve problems by coding to interfaces. Reading the book Head First: Design Patterns really helped things click for me.

bkildow
+3  A: 

To use the interface one can simply call the methods on an instance of the concrete class.

Typically you would have a variable typed to the interface type, thus allowing only access to the methods defined in the interface.

The obvious benefit is knowing of the functionality provided by the concrete class, irrespective of its specific implementation.

Sort of. Most importantly, it allows you to write APIs that take parameters with interface types. Users of the API can then pass in their own classes (which implement those interfaces) and you code will work on those classes even though they didn't exist yet when it was written (such as java.util.Arrays.sort() being able to sort anything that implements Comparable or comes with a suitable Comparator).

From a design perspective, interfaces allow/enforce a clear separation between API contracts and implementation details.

Michael Borgwardt
+3  A: 

Your understanding seems to be right on. Your co-worker just swung by your desk and has all the latest pics of the christmas party starring your drunk boss loaded onto his thumbdrive. Your co-worker and you do not think twice about how this thumbdrive works, to you its a black box but you know it works because of the USB interface.

It doesn't matter whether it's a SanDisk or a Titanium (not even sure that is a brand), size / color don't matter either. In fact, the only thing that matters is that it is not broken (readable) and that it plugs into USB.

Your USB thumbdrive abides by a contract, it is essentially an interface. One can assume it fulfills some very basic duties:

  1. Plugs into USB
  2. Abides by the contract method CopyDataTo:

    public Interface IUSB { void CopyDataTo(string somePath); //used to copy data from the thumbnail drive to... }

  3. Abides by the contract method CopyDataFrom:

    public Interface IUSB { void CopyDataFrom(); //used to copy data from your PC to the thumbnail drive }

Ok maybe not those methods but the IUSB interface is just a contract that the thumbnail drive vendors have to abide by to ensure functionality across various platforms / vendors. So SanDisk makes their thumbdrive by the interface:

public class SanDiskUSB : IUSB
 {
  //todo: define methods of the interface here
 }

Ari, I think you already have a solid understanding (from what it sounds like) about how interfaces work.

JonH
A: 

As I understand it, one creates interfaces to delineate expected functionality, and then implements these "contracts" in concrete classes.

The only sort of mutation i see in your thinking is this - You're going to call out expected contracts, not expected functionality. The functionality is implemented in the concrete classes. The interface only states that you will be able to call something that implements the interface with the expected method signatures. Functionality is hidden from the calling object.

This will allow you to stretch your thinking into polymorphism as follows.

SoundMaker sm = new Duck();<br/>
SoundMaker sm1 = new ThunderousCloud();

sm.makeSound(); // quack, calls all sorts of stuff like larynx, etc.<br/>
sm1.makeSound(); // BOOM!, completely different operations here...
Shaun F
I hate examples like this only because I think they confuse the hell out of the reader. Explanations are definately helpful. In this case I assume SoundMaker is some base class and makeSound is an abstract method of the SoundMaker class. Because it is a abstract method the Duck object defines this makeSound function to quack and the ThunderousCloud defines this function to go kaboom. Sorry but to beginners when I see a class Car or a Class Mammal it just irks me! SoundMaker could also be an interface in this case, which is what I think you mean.
JonH
JonH: Thanks and I agree. I should have included SoundMaker as an interface explicitly here to demonstrate it.
Shaun F