tags:

views:

118

answers:

10

As I understand interfaces they are contracts, I interpret it as the contract word, ie must have what is specified in the interface (ex open, close, read, write for an interface handling files).

But what im having a hard time grasping is why you would need to have an interface that tells you what the class must be able to do at all, wouldnt you know that already since you wrote it in the interface specification?

The only reason I can see for interfaces is in large projects where you want to be able to use a class without really knowing how it is built. By seeing what the interface requires will allow you to know how to use it.

Which leads me to wonder why I should use (or if I should) interfaces in projects that I will be the only one working on. Im pretty sure there are more uses for it that im not seeing.

I took most of my assumptions and interpretations from this question and this vbforums post

+4  A: 

You're right in that interfaces specify the contract but the implementaiton can be vastly different.

Simple example: lists in Java. List is an interface. Two common implementations are ArrayList and LinkedList. Each behaves different but honours the same contract. By that I mean that ArrayList has O(1) (constant) access whereas LinkedList has O(n) access.

If you don't yet understand what O(1) and O(n) mean, I suggest you take a look at the Plain english explanation of Big O.

The reason you do this even on your own code (ie something that isn't or won't be a public API) is to:

  • facilitate unit testing: you can mock up an interface whereas you can't (or can't easily) mock up a class; and
  • to allow you to change the implementation later without affecting the calling code.
cletus
+2  A: 

But what im having a hard time grasping is why you would need to have an interface that tells you what the class must be able to do at all, wouldnt you know that already since you wrote it in the interface specification?

It is also good when you are writing externally available code. In this case the code writer is not the user of the Interface. If you are delivering a library to users, you may want to document only the Interface, and allow the Class to change based on context or to evolve over time without changing the Interface.

akf
A good example of this is the Windows API which has versioned interfaces as the API has evolved over the years, ie. IMyInterface, IMyInterface2, IMyInterface3. Presumably client code would use the lowest common denominator it needed to to get the functionality it needs, which would have the added benefit of making your code backwards compatible to any version that implemented the interface you needed.
Matthew Scharley
+1  A: 

Suppose you're writing a set of classes that implements guns. You might have a Pistol, a Rifle, and a MachineGun. Then, suppose you decide to use these classes in such a way that you'd like to perform the fire() action on each of these guns. You could do it this way:

private Pistol p01;
private Pistol p02;
private Rifle  r01;
private MachineGun mg01;

public void fireAll() {
    p01.fire();
    p02.fire();
    r01.fire();
    mg01.fire();
}

That kind of sucks, because you have to change code in a few places if you add or remove guns. Or even worse, suppose you want to be able to add and remove guns at runtime: it becomes even harder.

Let's make an interface that each of the above guns will implement, call it Firearm. Now we can do this.

private Firearm[] firearms;

public void fireAll() {
    for (int i = 0; i < firearms.length; ++i) {
        firearms[i].fire();
    }
}

That lends itself to changes a little bit better, wouldn't you say?

phasetwenty
Good example, but the same could be said of an abstract base class called Firearm (which would make more sense in the context).
Matthew Scharley
Of course the interface can be defined in an abstract base class. That's the way you define interfaces in C++, which doesn't have a separate syntax for interfaces.
dewtell
A: 

If you ever want to revisit your old code, you will thank yourself for having built yourself some interfaces. Nothing is more frustrating than wanting to implementing a new type of something that exists, only to realize you do not remember what a new object had to have.

In Java, you can implement multiple interfaces, which sort of simulates multiple inheritance (an object with multiple parent objects). You can only extend one superclass.

AlbertoPL
+3  A: 

Interfaces are useful when you have two classes which need to work together but should be decoupled from each other as much as possible. A common example of this is when you use listeners to connect model and view together in the model-view-controller design pattern.

For example, let's say you had a GUI application where users could log in and log out. When users log out you might, say, change your "Currently logged in as So-and-So" label and close all of the visible dialog windows.

Now you have a User class with a logOut method, and whenever logOut is called you want all of these things to happen. One way to do that is have the logOut method handle all of these tasks:

// Bad!
public void logOut() {
    userNameLabel.setText("Nobody is logged in");
    userProfileWindow.close();
}

This is frowned upon because your User class is now tightly coupled to your GUI. It would be better to have the User class be dumber and not do so much. Instead of closing userProfileWindow itself it should just tell userProfileWindow that the user has logged out and let userProfileWindow do whatever it wants to do (it wants to close itself).

The way to do this is by creating a generic UserListener interface with a method loggedOut that is called by the User class when the user logs out. Anybody who wants to know when the user logs in and logs out will then implement this interface.

public class User {
    // We'll keep a list of people who want to be notified about logouts. We don't know
    // who they are, and we don't care. Anybody who wants to be notified will be
    // notified.
    private static List<UserListener> listeners;

    public void addListener(UserListener listener) {
        listeners.add(listener);
    }

    // This will get called by... actually, the User class doesn't know who's calling
    // this or why. It might be a MainMenu object because the user selected the Log Out
    // option, or an InactivityTimer object that hasn't seen the mouse move in 15
    // minutes, who knows?
    public void logOut() {
        // Do whatever internal bookkeeping needs to be done.
        currentUser = null;

        // Now that the user is logged out, let everyone know!
        for (UserListener listener: listeners) {
            listener.loggedOut(this);
        }
    }
}

// Anybody who cares about logouts will implement this interface and call
// User.addListener.
public interface UserListener {
    // This is an abstract method. Each different type of listener will implement this
    // method and do whatever it is they need to do when the user logs out.
    void loggedOut(User user);
}

// Imagine this is a window that shows the user's name, password, e-mail address, etc.
// When the user logs out this window needs to take action, namely by closing itself so
// this information isn't viewable by other users. To get notified it implements the
// UserListener interface and registers itself with the User class. Now the User.logOut
// method will cause this window to close, even though the User.java source file has no
// mention whatsoever of UserProfileWindow.
public class UserProfileWindow implements UserListener {
    public UserProfileWindow() {
        // This is a good place to register ourselves as interested observers of logout
        // events.
        User.addListener(this);
    }

    // Here we provide our own implementation of the abstract loggedOut method.
    public void loggedOut(User user) {
        this.close();
    }
}

The order of operations will look like this:

  1. The application starts and a user logs in. She opens her UserProfileWindow.
  2. The UserProfileWindow adds itself as a UserListener.
  3. The user goes idle and doesn't touch the keyboard or mouse for 15 minutes.
  4. An imagined InactivityTimer class notices and calls User.logOut.
  5. User.logOut updates the model, clearing the currentUser variable. Now if anybody asks, there's nobody logged in.
  6. User.logOut loops through its listener list, calling loggedOut() on each listener.
  7. The UserProfileWindow's loggedOut() method is invoked, which closes the window.

This is great because this User class knows absolutely nothing about who needs to know about log out events. It doesn't know that the user name label needs to be updated, that the profile window needs to be closed, none of that. If later we decide more things need to be done when a user logs out, the User class does not need to be changed at all.

So, the listener pattern is one example of where interfaces are super useful. Interfaces are all about decoupling classes, removing ties and dependencies between classes that need to interact with each other but should not have strong ties in their code to each other.

John Kugelman
This is amazing stuff to me and a real eyeopener in more ways then just interface usage. But to open them even more I would love to see the rest of that code snippet with the things "in action" to follow it. Could you please paste some more into it? :)
Patrik Björklund
Thanks a million for that very explaining edit! The size of the lightbulb over my head is enormous right now. Is the usage of interfaces in this way specific (or more common) to Java?
Patrik Björklund
+1  A: 

Let's say you have two classes Car and Gorilla. These two classes have nothing to do with each other. But, let's say you also have a class that can crush things. Instead of defining a method that takes a Car and crushes it and then having a separate method that takes a Gorilla and crushes it, you make an Interface called ICrushable ...

interface ICrushable
{
  void MakeCrushingSound();
}

Now you can have your car and your Gorilla implement ICrushable and your Car implement ICrushable and your crusher can then operate on an ICrushable instead of a Car and a Gorilla ...

public class Crusher
{
  public void Crush(ICrushable target)
  {
    target.MakeCrushingSound();
  }
}

public class Car : ICrushable
{
    public void MakeCrushingSound()
    {
        Console.WriteLine("Crunch!");
    }
}

public class Gorilla : ICrushable
{
    public void MakeCrushingSound()
    {
        Console.WriteLine("Squish!!");
    }
}

static void Main(string[] args)
{
  ICrushable c = new Car();      // get the ICrushable-ness of a Car
  ICrushable g = new Gorilla();  // get the ICrushable-ness of a Gorilla

  Crusher.Crush(c);
  Crusher.Crush(g);
}

And Viola! You have a Crusher that can crush Cars and get "Crunch!" and can crush Gorillas and get "Squish!". Without having to go through the process of finding a type-relationship between Cars and Gorillas and with compile-time type checking (instead of a runtime switch statement).

Now, consider something less silly ... an Class that can be compared (IComparable) for example. The class will define how you compare two things of it's type.

Per comment: Okay, let's make it so we can sort an array of Gorillas. First, we add something to sort by, say Weight (please ignore the dubious business logic of sorting Gorillas by weight ... it's not relevant here). Then we implement ICompararble ...

public class Gorilla : ICrushable, IComparable
{
    public int Weight
    {
        get;
        set;
    }

    public void MakeCrushingSound()
    {
        Console.WriteLine("Squish!!");
    }

    public int CompareTo(object obj)
    {
        if (!(obj is Gorilla))
        {
            throw (new ArgumentException());
        }

        var lhs = this;
        var rhs = obj as Gorilla;

        return (lhs.Weight.CompareTo(rhs.Weight));
    }

}

Notice we have "gotten around" the restriction of single inheritance that many languages have. We are allowed to implement as many interfaces as we like. Now, just by doing that, we can use functionality that was written more than 10 years ago on a class I just wrote today (Array.Sort, Array.BinarySearch). We can now write the following code ...

var gorillas = new Gorilla[] { new Gorilla() { Weight = 900 },
                               new Gorilla() { Weight = 800 },
                               new Gorilla() { Weight = 850 }
};

Array.Sort(gorillas);
var res = Array.BinarySearch(gorillas, 
    new Gorilla() { Weight = 850 });

My Gorillas get sorted and binary search finds the matching Gorilla with the Weight of 850.

JP Alioto
I remember using IComparable for my last assignment, if im not totally wrong I remember that you could not compare objects that did not implement this interface which if correct would explain even more about the use of interfaces to me!
Patrik Björklund
A: 

No one forces you to write interface and there is no language enforces that even. Its a best practice and idiom that a good programmer would follow. You are the only one to use your code, and ya, you can write what you like but what if you leave the project and someone else has to maintain and/or extend it? Or what if some other projects consider using your code? Or even what if after a while, you have to revisit your code for adding features or refactoring? You would create a nightmare for these sorts of things. It will be hard to understand what your object relationships and contracts established b/w them.

jimx
Thats why im trying to understand why it's good to use them, to avoid making horrid mistakes now that can affect me or others in the future.. Im not "for" or "against" interfaces, im trying to build knowledge.
Patrik Björklund
Right. I did express the possible bad consequences, less maintainability, more dependencies, much less clean code. It should also be good for you to code because as long as you keep the contract, how you implement them are all freestyle, great for ploymorphism.
jimx
A: 

Abstraction: Code written to use an interface is reusable an never needs to change. In the below case, the sub will work with System.Array, System.ArrayList, System.Collection.CollectionBase, List of T, because they all implement IList. An existing class can easily implement an interface even when the class inherits another class. You could even write your class to implement IList to us in the sub. Or another program could also implement the interface to use in the sub.

public sub DoSomething(byval value as IList) end sub

You can also use multiple interfaces in a class, so a class can be both a IList and IEnumerable, in most languages you can on inherit one class.

I would also look at how they are used in the various frameworks.

eschneider
A: 

Hi,

As I understand your question why do we need Interfaces ? right ? Well we don't need them :)

In C++ for example, when you define a template... say a dummy function that looks like ::

template <typename T>
void fun(const T& anObjectOfAnyType)
{
    anyThing.anyFunction();
}

you can use this function anywhere with any type that has a function called anyFunction... the only thing that the compiler is going to do, is to replace T with the name of the type, and compile the new piece of code...

This is very error prone in fact. The reason is that if we plug in a type which does not have a anyFunction then we are going to get an error, that error is different every time, every line that can not be translated by the compiler will issue an error for it. You get A LOT of errors for the ONLY MISSING THING! The new type does not have the required functions to work correctly with our fun for example.

Now interfaces solve this whole issue, how ? If the type has the required functions, then it is suitable, if not then the compiler will issue an error that the type is not suitable.

The template example is just for clarification, and if you want to imaging what will happen if java is without interfaces, then the only thing you have to do is to check for the existence of every function manually in every class, where you assume that class implements a particular function. The dirty work is done by the compiler :)

Thanks,

AraK
A: 

an interface reduces what the client is dependent on (http://en.wikipedia.org/wiki/Dependency_inversion_principle). it allows for multiple implementations and the ability to change implementations at run time.

Ray Tayek