45

Possible Duplicate:
Why are interfaces useful?

Like most faculty, my java faculty introduced interface without explaining or even mentioning its practical use. Now I imagine interfaces have a very specific use, but can't seem to find the answer.

My question is: a class can directly implement the functions in an interface. eg:

interface IPerson{
    void jump(int); 
}

class Person{
int name;
    void jump(int height){
        //Do something here
    }
}

What specific difference does

class Person implements IPerson{
    int name;
    void jump(int height){
        //Do something here
    }
}

? make

3
  • 3
    Why are interfaces useful?
    – gnat
    Apr 21, 2012 at 12:11
  • It would be less confusing if you named the interface better. I would have called it IJumper. This is the interface that allows things to Jump (as a distinct group which may be larger than the Person group). Apr 21, 2012 at 16:28
  • Wait, are you asking why the interface must be explicitly declared? It doesn't. Google's Go language uses interfaces with implicit interface (if you have a void jump(int) method, then you are an IPerson). Haskell is very strongly typed, but also uses type inference and some very nifty stuff with TypeClasses to handle similar situations. Apr 21, 2012 at 22:41

10 Answers 10

19

Remember, Java is finicky about type.

Let's extend your example a bit and rename the class to Jumpable.

interface Jumpable {
    void jump(int);
}

class Person extends Mammal implements Jumpable {
    //other stuff
    void jump(int howHigh) {
        //jump method
    }
}

class Dog extends Mammal implements Jumpable {
    //other stuff
    void jump(int howHigh) {
        //jump method
        //also make him bark when he jumps
    }
}

class Cat extends Mammal implements Jumpable {
    //other stuff
    void jump(int howHigh) {
        //jump method
        //make it stretch its legs as well
    }
}

class FlyingFish extends Fish implements Jumpable {
    //other stuff
    void jump(int howHigh) {
        //jump method
        //make it come out of water
    }
}

class Mantis extends Insect implements Jumpable {
    //other stuff
    void jump(int howHigh) {
        //jump method
        //make it come out of water
    }
}

class Ant extends Insect { //Cannot jump
    //other stuff
}

class Whale extends Mammal { //Cannot jump (hopefully)
    //other stuff
}

Note that here we have a variety of classes, organised in some hierarchy. Not all of them can jump, and jump-ability is not universally applicable to any category--each parent class (Animal, Mammal, Insect, Fish).

Lets say we want to hold a jumping competition. Without interfaces, we would have to do something like this:

void competition(
    Person[] pCompetitors,
    Dog[] dCompetitors,
    Cat[] cCompetitors,
    FlyingFish[] fCompetitors,
    Mantis[] mCompetitors
) {
    for(int i=0; i<pCompetitors.length; i++) {
        pCompetitors[i].jump((int)Math.rand() * 10);
    }
    //Do the same for ALL the other arrays.
}

Here, since there is no "enveloping class" that holds all classes that can jump, we have to invoke them individually. Remember, we cannot just have an Animal[] or Mammal[] array, since the compiler won't allow us to invoke jump(); and not all Animals/Mammals can jump().

Also, this becomes impossible to extend. Lets say you want to add another jumping class.

class Bob extends Animal { //Bob is NOT a human. Bob is something....else....
    void jump(int howHigh) {
        //...
    }
}

Now, you have to modify competition(.........) to accept a Bob[] parameter as well. You also have to modify all instances of competition[] to either create their own Bob[]s, or pass empty Bob[] parameters. And it gets icky.


If you used interfaces, your competition method becomes thus:

void competition(Jumpable[] j) {
    for(int i=0; i<j.length; i++) {
        j[i].jump((int)Math.rand() * 10);
    }
}

This can be extended without any hassle as well.

Basically, interfaces let the compiler know the expected behavior of the object -- what methods/data the compiler can assume exist. That way we can write general programs.

Also you can multiple-inherit interfaces, you can't do that with extends in Java.

Some real-world examples: The first one that comes to mind is the event handlers of AWT. These allow us to pass a method as a parameter and make it an event handler. This will only work if the compiler is certain that the method exists, and thus we use interfaces.

99

It starts with a dog. In particular, a pug.

A pug

The pug has various behaviors:

public class Pug
{
    private String name;

    public Pug(String n)
    {
        name = n;
    }

    public String getName()
    {
        return name;
    }

    public String bark()
    {
        return "Arf!";
    }

    public boolean hasCurlyTail()
    {
        return true;
    }
}

Labrador Retriever

And you have a Labrador, who also has a set of behaviors.

public class Lab
{
    private String name;

    public Lab(String n)
    {
        name = n;
    }

    public String getName()
    {
        return name;
    }

    public String bark()
    {
        return "Woof!";
    }

    public boolean hasCurlyTail()
    {
        return false;
    }
}

We can make some pugs and labs:

Pug pug = new Pug("Spot");
Lab lab = new Lab("Fido");

And we can invoke their behaviors:

pug.bark()           -> "Arf!"
lab.bark()           -> "Woof!"
pug.hasCurlyTail()   -> true
lab.hasCurlyTail()   -> false
pug.getName()        -> "Spot"
lab.getName()        -> "Fido"

Two cute dogs in a cage

Let's say I run a dog kennel and I need to keep track of all the dogs I'm housing. I need to store my pugs and labradors in separate arrays:

public class Kennel
{
    Pug[] pugs = new Pug[10];
    Lab[] labs = new Lab[10];

    public void addPug(Pug p)
    {
        ...
    }

    public void addLab(Lab l)
    {
        ...
    }

    public void printDogs()
    {
        // Display names of all the dogs
    }
}

But this is clearly not optimal. If I want to house some poodles, too, I have to change my Kennel definition to add an array of Poodles. In fact, I need a separate array for each kind of dog.

Insight: both pugs and labradors (and poodles) are types of dogs and they have the same set of behaviors. That is, we can say (for the purposes of this example) that all dogs can bark, have a name, and may or may not have a curly tail. We can use an interface to define what all dogs can do, but leave it up to the specific types of dogs to implement those particular behaviors. The interface says "here are the things that all dogs can do" but doesn't say how each behavior is done.

public interface Dog
{
    public String bark();
    public String getName();
    public boolean hasCurlyTail();
}

Then I slightly alter the Pug and Lab classes to implement the Dog behaviors. We can say that a Pug is a Dog and a Lab is a Dog.

public class Pug implements Dog
{
    // the rest is the same as before
}

public class Lab implements Dog
{
    // the rest is the same as before
}

I can still instantiate Pugs and Labs as I previously did, but now I also get a new way to do it:

Dog d1 = new Pug("Spot");
Dog d2 = new Lab("Fido");

This says that d1 is not only a Dog, it's specifically a Pug. And d2 is also a Dog, specifically a Lab.

We can invoke the behaviors and they work as before:

d1.bark()           -> "Arf!"
d2.bark()           -> "Woof!"
d1.hasCurlyTail()   -> true
d2.hasCurlyTail()   -> false
d1.getName()        -> "Spot"
d2.getName()        -> "Fido"

Here's where all the extra work pays off. The Kennel class becomes much simpler. I need only one array and one addDog method. Both will work with any object that is a dog; that is, objects that implement the Dog interface.

public class Kennel 
{
    Dog[] dogs = new Dog[20];

    public void addDog(Dog d)
    {
        ...
    }

    public void printDogs()
    {
        // Display names of all the dogs
    }
 }

Here's how to use it:

 Kennel k = new Kennel();
 Dog d1 = new Pug("Spot");
 Dog d2 = new Lab("Fido");
 k.addDog(d1);
 k.addDog(d2);
 k.printDogs();

The last statement would display:

 Spot
 Fido

An interface give you the ability to specify a set of behaviors that all classes that implement the interface will share in common. Consequently, we can define variables and collections (such as arrays) that don't have to know in advance what kind of specific object they will hold, only that they'll hold objects that implement the interface.

7
  • 2
    Great explanation BB :)
    – Rocklan
    Apr 23, 2012 at 6:12
  • 3
    This is the best definition out of the top 3. You've really got to the bottom of why it doesn't make sense to avoid implementing an interface. ie classes implementing interfaces can have their objects declared as the interface to pass to methods/ classes. Any other reasons?
    – dewd
    Feb 11, 2014 at 19:34
  • very nice. helped my lots
    – Robert
    Jul 23, 2015 at 3:49
  • 6
    In your example Dog is an interface, and Pug/Lab implement Dog, and you say We can say that a Pug is a Dog and a Lab is a dog. But no, an interface is not what you "are" it's what you "do". So Dog should have been a base class, because Pug/Lab ARE dogs, rather than being objects that implement dog behaviour.
    – 404
    Feb 9, 2016 at 20:20
  • 2
    @eurotrash From a theoretical perspective the only observable properties of a type are its behaviors. An interface is just a special name for a type which has no concrete behaviors. In a language that allows multiple inheritance, an interface is indistinguishable(modulo programming language warts) from a virtually inherited abstract base class, exactly for this reason. Feb 26, 2018 at 16:55
29

Having an IPerson interface allows you to have multiple implementers (Man, Woman, Employee etc...), but still treat them all through the interface in other classes.

So, in another class you simply state:

void myMethod(IPerson person, Integer howHigh)
{
   person.jump(howHigh);
}

You don't have to have a separate method for each implementer.

5
  • 1
    +1, 'nuff said. It'll become clearer once you get to the concept of polymorphism. Apr 21, 2012 at 10:26
  • 2
    SO you could pass an object of any class as long as it implements the same interface?
    – SoWhat
    Apr 21, 2012 at 12:00
  • 2
    @SomeshMukherjee - correct.
    – Oded
    Apr 21, 2012 at 12:34
  • 1
    To add to that: Interfaces also provide a degree of information hiding because they limit knowledge of the object to just what the interface defines. If a Man and Woman have other methods beyond what's in IPerson, they're completely invisible to anything referring to the objects using that interface.
    – Blrfl
    Apr 21, 2012 at 16:08
  • Ironic, this is the tl;dr version of the answer directly above it. +1 to both of you. Nov 26, 2012 at 17:49
14

The purpose of an interface is not to relocate or reuse code but more to ensure that some methods that operate on a wide range of types can use these types (which will be passed to them as arguments) in the exact same way even though they may not have common parent classes.

Interface is used to make the contract - the expected functionaity to exist in a certain class.

For example:

interface Transmittable {
     public byte[] toBytes();
}

class Person implements Transmittable {
     public byte[] toBytes() {
         return this.name.getBytes()
    }
}

class Animal implements Transmittable {
     public byte[] toBytes() {
            return this.typeOfAnimal.getBytes()
    }
}

class NetworkTransmitter {
     public void transmit(Transmittable object) {
          byte data[] = object.toBytes();
         //do something....
     } 
}

class TestExample {
    public static void main(String args[]) {
           NetworkTransmitter trobj = new NetworkTransmitter();
           trobj.transmit(new Person());
           trobj.transmit(new Animal());
   }
}

Note that this is not like inheritance where object of one class inherits (or overrides) a method of the same name from the parent. The classes that implement a interface need not be descendant from the same parent class but other classes that want to ensure a contract exists, can call the same methods on objects of all classes that implement the interface. Interface ensures that this contract is available.

1
  • +1 Interface is used to make the contract.- That's exactly the point. Apr 21, 2012 at 13:01
3

I think all developers can understand your confusion - trying to get your head around the use of interfaces isn't always explained well. I began to really understand the use of interfaces when I started working as a developer on real world projects.

There is a great article at BlackWasp, which explains the use of an interface with a brilliant example - have a read and try it out, it really helped me to understand it better:

http://www.blackwasp.co.uk/Interfaces.aspx

1

I think your confusion comes down to badly named classes and interfaces in the the example.

Personally I think it would be less confusing if you named the interface better as IJumper. This is the interface that allows things to Jump (as a distinct group which may be larger than the Person group).

If you wanted to stay with the same analogy. I would rename Person to EarthPerson. Then you can have alternative classes that implement the IPerson interface such as MarsPerson, JupitorPerson etc..

All of these different people will be able to Jump but how they jump will depend on how they evolved. Yet your code will work for people from other planets without any modification as you provided a generic interface that works with IPerson rather than a person from an explicit planet.

This also makes it easier to test your code.

If for example the Person object is very expensive to create (it looks up all the details of a person in the Earth Wide DB). When testing you don't want to use a real Person object as the data (take a while to create) and may change over time and break your test. But you can create a TestPerson (which implements the IPerson interface) object (a mock of a Person) and pass that to any interfaces that accept a person and make sure they do the correct thing.

2
  • I suppose that is true. I wanted to know what programmatic use of an interface would be
    – SoWhat
    Apr 21, 2012 at 16:40
  • 1
    @SomeshMukherjee: It allows you to write your code so that works for all people without needing to know what planet they are from. So it de-couples your code from specific implementations thus making it more robust/testable and easier to maintain. Apr 21, 2012 at 16:43
1

There are very interesting use cases of having an interface. Here's one:

Suppose I am creating a OS monitoring system and you tell me what to do after occurrence of a certain event. Say when the disk space is >90% full or cpu usage is very high or when some user has logged in etc. I am still monitoring it, but it's the responsibility of the client code to provide the what happens now functionality.

In my code (that's the OS monitoring system), I will expect you to provide me an Object with certain methods implemented. Say some method like void OnDiskUsageHigh() etc. In my code I'd simply call this method of yours when disk space goes down.

This is a callback mechanism, and without the interface and the defined set of policies between you and me my code won't be able to service a general set of clients.

Here's the interface you should implement (i.e. make a concrete class):

interface Callback { 
  void OnDiskUsageHigh();
  void OnCpuUsageHigh();
  ...
} 

And you initialize my OSMonitoring class with an object whose class implements Callback as in

new OSMonitoringTool(new ConcreteCallbackClass());

You should read some more about policy/contract based programming.

1

Using an interface allows you to cast a number of different classes as a common type, regardless of how the individual classes might be implemented.

Here's a quick and dirty example:

class Puppet : IMovement { ... }
class Vehicle : IMovement { ... }
class Car : Vehicle { ... }
class Bicycle : Vehicle { ... }

class Person : IMovement { ... }
class Child : Person { ... }
class Adult : Person { ... }

As per the example, each of the classes implements the IMovement interface, either directly or indirectly. However, the important thing to note is that any of the classes in the example could be cast as the same common interface type:

((IMovement)puppet).Move()
((IMovement)car).Move()
((IMovement)child).Move()

Interfaces allow you to easily introduce new behaviour to your classes without altering their existing interfaces. Thus an interface allows for polymorphism independent of inheritance. This is very useful when you are trying to handle a number of completely different types of object in a similar manner.

2
  • Do you call this a cast in Java? Urgh. It's a reference cast, or base-class-pointer cast as we'd call it in C++. Which does not actually cast the object in the sense that anything changes about its implementation (like when you cast a float to double), it just creates are more general pointer that can dispatch over the class hierarchy's vtable. IMO quite an important distinction. Apr 21, 2012 at 23:20
  • 1
    @leftaroundabout I don't recall calling this a cast in any language in particular. Yes, it's ugly, but the point being made isn't about how to cast, but rather that the interface allows each of the classes represented to be called in the same way. I'm aware that I could have use an "as" operator, or that I could have simply passed each object to a method. As a quick example however ugly, this allows me to make a specific point, in the simplest manner I could think of.
    – S.Robins
    Apr 22, 2012 at 1:14
0

In addition to the comments of others, interfaces make it easier to do testing since you've clearly defined what the critical parts of the interface should be for any mock/stub classes. TDD should be doing interfaces all over the place.

0

There is no need to do so, unless you want to be able to have more than one class providing that behavior.

A good example is the JDBC Connection interface which represents a connection to an SQL database, where you as the programmer can send SQL commands and get the result back. You do not care how the underlying driver talks to the database but you do care that the implementation implements the Connection interface, so you can just use any connection that the DriverManager choose to give you.

Not the answer you're looking for? Browse other questions tagged or ask your own question.