views:

1585

answers:

26

For a few years I was a teaching assistant for an introduction to programming module - Java for first year undergraduates.

Mostly it went well and we managed to get object-oriented programming across to the students quite well, but one thing that students rarely saw the point of was interfaces.

Pretty much any explanation we gave either came across as too contrived to be useful for learning, or too far removed from their position as beginners. The reaction we tended to get was "I... see," translated as "I don't understand and they don't sound useful".

Anyone here have a way of successfully teaching students about interfaces? I'm not a teaching assistant any more, but it's always nagged at me.

A: 

In this previous question there are some good scenarios that explain the whys behind the use of interfaces.

Stack Overflow Question

Antonio Louro
+10  A: 

"Where classes ARE something, typically interfaces DO something. So I might have a car, but I would never go "carring" but I might go driving... so my Car might implement "drivable" interface."

EDIT:

Mark brings up a good point. Interfaces don't do anything at all, but instead define what behaviors happen. And, he also brings up a good point about not wanting to confuse the audience. Not that it's okay to confuse seasoned developers, but it's definitely not a good idea to confuse a brand new student. In light of this, I'm revising my one-liner into a many-liner.

"Where classes define existence, interfaces define behavior. Classes define what something is, while interfaces define what something does. So I might have a car, and it has things like an Engine, how much gas it has, what it's historic MPG is, and the like, but I would never go "carring". I might, on the other hand, go Driving... can my Car drive? It can if I give it a Drive method. I can also have "Driveable" interface with a drive method, and leave it up to the car to determine what driving really means. Now, if I only have cars it's not a big deal to have an interface. But what about trucks? If they both are Drivable, I can simply have a List<Drivable for both of them. Of course, the observant student says "Why can't Car and Truck both simply extend Vehicle, with an abstract Drive method?" Which, actually is a very valid notion. But, what about the Space Shuttle? Very few of the components between Car and Truck apply to the Space Shuttle, so it doesn't seem well suited to extend the Vehicle class. Or what about future cars? We have no idea what they might be like, they might not have chassises, they might just be bubbles of energy that move us around, but we might still call their behavior drive()."

breathes

Now that paragraph/essay is a little verbose, but I could see, with some slides or a chalkboard, being effective for first year students to get their head around (assuming they understand abstract classes first anyway).

glowcoder
"interfaces DO something" might mislead people given that interfaces cannot have implementations. Maybe "interfaces say what something can do"? I don't have a great alternative.
Mark Peters
A valid point, Mark. I'll revise based on this insight. Thanks!
glowcoder
How about "a class combines a published list of interactions with default implementations of those interactions; an interface only lists the interactions. Any given class can have only one set of default implementations for things, and may thus only inherit from one other class, but can define any number of interactions."?
supercat
@supercat - That's very confusing. Published list of interactions? Set of default implementations for things? They'll just stare at him like he's speaking Greek.
kirk.burleson
+1 for an excellent rephrasing of an explanation that could be misinterpreted.
Caleb Thompson
A: 

Interfaces provide a look at what a class needs to do for instance you can have an Animal interface and lets say that has a method called speak(), well each animal can speak but they all do it differently but this allows you to cast anything that implements animal to animal so you can have a List of animals and make them all speak but use their own implementation. Interfaces are simply wrappers for these kinds of things.

Jesus Ramos
+1  A: 

Do you teach JDBC as well? Take it as an example. It's an excellent real world example of how powerful interfaces are. In JDBC you're writing code against an API which exist of almost only interfaces. The JDBC driver is the concrete implementation. You can easily reuse the JDBC code on many DB's without rewriting the code. You just have to switch the JDBC driver implementation JAR file and driver class name to get it to work on another DB.

At least, using interfaces offers you the possibility to change from the concrete implementation (the code logic which is responsible for the behaviour) at some way/point without rewriting the whole code. Try to use real world examples when explaining things. It would make more sense.

BalusC
+3  A: 

This explains best : (referenced from this tutorial)

There are a number of situations in software engineering when it is important for disparate groups of programmers to agree to a "contract" that spells out how their software interacts. Each group should be able to write their code without any knowledge of how the other group's code is written. Generally speaking, interfaces are such contracts. For example, imagine a futuristic society where computer-controlled robotic cars transport passengers through city streets without a human operator. Automobile manufacturers write software (Java, of course) that operates the automobile—stop, start, accelerate, turn left, and so forth. Another industrial group, electronic guidance instrument manufacturers, make computer systems that receive GPS (Global Positioning System) position data and wireless transmission of traffic conditions and use that information to drive the car.

The auto manufacturers must publish an industry-standard interface that spells out in detail what methods can be invoked to make the car move (any car, from any manufacturer). The guidance manufacturers can then write software that invokes the methods described in the interface to command the car. Neither industrial group needs to know how the other group's software is implemented. In fact, each group considers its software highly proprietary and reserves the right to modify it at any time, as long as it continues to adhere to the published interface.

More Link: http://download-llnw.oracle.com/javase/tutorial/java/concepts/interface.html

YoK
+18  A: 

If you are trying to explain it to beginners I would stick with the idea that interfaces can promote code reuse and modularity within the code:

For example lets say we are going to paint some objects:

public class Painter {
    private List<Paintable> paintableObjects;

    public Painter(){
       paintableObjects = new ArrayList<Paintable>();
    }

    public void paintAllObjects(){
        for(Paintable paintable : paintableObjects){
            paintable.paint();
        }
    }
}

public interface Paintable {
     public void paint();
}

Now you could explain to the students that without Paintable interface the Painter object would need to have methods to paint certain types of objects, like a method called paintFences() and paintRocks() and we would need to have a new Collection for each type of objects we want the painter to be able to paint.

But thankfully we have interfaces which make painting objects a breeze and how objects are painted is left entirely up to classes that implement the Paintable interface.

EDIT

Another benefit that I forgot to mention is that if you ever need to add new object to paint to your code base, all you need to do is create a new class that implements Paintable and the Painter class never has to change. In this sense the Painter class is never dependent upon the objects it is going to paint, it only needs to be able to paint them.

EDIT 2

James Raybould reminded me of a key use of interfaces I forgot to mention: Having an interface between your components, like the Paintable objects and Painter objects, allows you to more easily develop with other people. One developer can work on the Painter objects and another can work on the Paintable objects and all they have to do to function properly together is define a common interface beforehand that they will both use. I know when I've worked on projects with other people in college level projects its really helpful when you are trying to have everyone work on different parts of the project and still have all components come together nicely in the end.

tkeE2036
Interfaces should not be prepended with "I" (Java's coding convention).
Steve Kuo
@Steve Kuo:Good point. I'll update my post.
tkeE2036
but it can - eclipse's and apache's code convention.
01
Ah well either way that is an argument for a different post :)
tkeE2036
This is a really nice example, and would probably go over very well. I think realistically though, as James says, students simply have to encounter an uncontrived situation where they need to use an interface, and then the "why and where" of interfaces will click.
Andy
@Andy True but you asked for a way that would show students the point of interfaces in the classroom. I think this example gets the idea of when to use interfaces and the benefits it can provide. This lesson could easily be accompanied by a project that would really push this idea home. Saying that students have to wait until they encounter an uncontrived situation is kind of saying that they can't learn it in the classroom. Yes learning it in an uncontrived situation is one way to learn this but you asked how could this be accomplished in the classroom.
tkeE2036
@tkeE2036 I think overall, interfaces will remain one of those things that students can be taught the mechanics of, but to really understand why they should use them needs real experience. Regardless, you gave a truly good example that I wish I'd had when I was teaching.
Andy
+7  A: 

Well, recently, I happened to explain this to someone close. The way I explained the question "why Interfaces?", is by taking example of of the USB Port and the USB drives.

The USB port can be considered as a specification, and any USB drive can fit into it, provided they implement the specification. So in this case, the port becomes the Interface and the numerous types of USB sticks available, become the class. Carrying this example ahead, if I were to supply someone an USB drive (class), I would not need to tell them (the calling method) as to what am I passing across. Had the calling method taken a USB drive (class type) as a reference, I would not have been able to pass any but only the USB drive that the port is meant for.

To sum it up, Intefaces, help the caller be comptabile with the calling method (in a use-case when the calling method expects an instance of a particular type), no matter what instance you pass across, the caller as well as the callee are sure that it (instance) would fit into the Interface reference (the USB port for analogy).

PaiS
I like this explanation. Not only is it a good analogy, but "interface" can be used with hardware without any confusion.
Brian S
A: 

The real value of interfaces comes with being able to override components in 3rd party APIs or frameworks. I would construct an assignment where the students need to override functionality in a pre-built library that they cannot change (and do not have the source for).

To be more concrete, let's say you have a "framework" that generates an HTML page implemented as a Page class. And page.render(stream) generates the html. Let's say that Page takes an instance of the sealed ButtonTemplate class. The ButtonTemplate object has its own render method so that in page.render(stream) buttonTemplate.render(label,stream) gets called anywhere there is a button and it produces the html for a submit button. As an example to the students, let's say that we want to replace those submit buttons with links.

I wouldn't give them much direction other than describing the final output. They will have to pound their heads trying various solutions. "Should we try to parse out the button tags and replace with anchor tags? Can we subclass ButtonTemplate to do what we want? Oh, wait. It's sealed! What were they thinking when they sealed this class!?!" Then after that assignment show a second framework with the ILabeledTemplate interface with the render(label,stream) method.

SargeATM
`sealed`? I think you mean `final`. This is Java we're talking about :P
Brian S
+7  A: 

I usually use "contract" but "promises solemnly to provide" might also help understanding.

Thorbjørn Ravn Andersen
so you made the class put on a straight face and swear on a bible that it will provide the functions and fields listed in interface? :P
RCIX
@RCIX, please reread the question. This is a teaching situation - the _students_ may imagine that and understand the real concept better. Where is your sense of abstraction?
Thorbjørn Ravn Andersen
A: 

In addition to the other answers, you could try explaining it from a different perspective. The students I'm sure already know about inheritance because it is jammed down the throats of every Java student from probably lecture one. Have they heard about multiple inheritance? Method resolution was seen as a design issue in C++ (and also in Perl and other multiple-inheritance languages) because conceptually it's ambiguous as to exactly what should happen when a method is called in a subclass that is defined in two of its base classes. Are both executed? Which one goes first? Can one be referenced specifically? See also the diamond problem. It's my understanding that this confusion was resolved simply by introducing interfaces, which have no implementation, so there's no ambiguity as to which implementation to use during method resolution.

bowenl2
A: 

If a class needed to handle exactly one piece of abstract functionality, and didn't need to inherit any other class, one could use an abstract class to expose the functionality and then derive the real class from that. Notice the two items in italics, however. Interfaces make it possible for a class to behave as several independent types of abstract things, even if the class is derived from another class that does not behave as those types of things. Thus, interfaces satisfy one of the main usage cases for multiple inheritance, without the ickiness that goes along with multiple inheritance.

A simple real-world example of a very practical interface: iEnumerable. If a class holds some arbitrary number of some type of item, is is very useful for another class to act upon all of those item without having to worry about the particulars of the object that holds them. If "enumerableThing" were an abstract class, it would be impossible for an object of any class which derived from something that wasn't an "enumerableThing" to be passed to code that expected an enumerableThing. Since any class, including derived classes, can implement enumerableThing without regard for whether the base classes do so, it's possible to add enumeration ability to any class.

supercat
+18  A: 

In explaining interfaces and object oriented concepts in general to non-programmers, I always use the home entertainment system analogy.

The DVD player, TV, Cable Box, Remote Control are all objects that encapsulate complicated and sophisticated functionality. However, they have interfaces to each other and to the Humans that operate them that largely hide the lion share of that complexity.

The video in jack of a TV is an interface that is implemented by the DVD player and the cable box and a number of other types of devices.

I suspect it would be possible and perhaps an educational exercise for a student to describe their own home entertainment system entirely using Java code.

aepryus
I consider this the best real world example of all answers. I wish I could upvote it twice :-)
meriton
+1: The use of the word 'interface' in software might even historically have derived from its use in hardware.
Don Roby
+5  A: 

I recommend the first chapter of Head First Design Patterns for this. The Duck simulation explains the problem with using inheritance, and the rest of the chapter goes on explaining how to do it.

JRL
+1 The use of interfaces in design patterns was a key break-through for me for understanding interfaces.
David Relihan
+4  A: 

Well i just explained interfaces to a work partner, she was learning java from progress and she really did not get all the OOP stuff at the beggining so i just explained everything from a non software engineering point of view, my explanation for interfaces where something like this:

"Supose you want to hire a plumber to fix some things on your house, you dont know (and you dont care much) who you may end up hiring but you know what he/she must be able to do, so you define a set of tasks that any one that claims to be a plumber must know how to do, of course everybody migth have its own way of carrying out each task but in the end teh person you are hiring is a plumber because it knows how to do each task, so if you where to write this in java the first thing to do would be to define an interface plumber like this:

public interface Plumber
{ //silly code here }

ok then, lets say that i know how to do each task you are requesting for and so im fully ciomplaint with your requirements and so acording to you im a plumber, so today i decide to be your plumber and you decide to hire me (yay!), based on the las example, you can say that im a person that knows how to develop sowftware and plumbing in a specific way, if i were to write code for me as a class i could write something like this:

public class Rick extends Person implements SoftwareDeveloper, Plumber

and later you could fix things in your house using me as your plumber:

Plumber thePlumber = rick;
thePlumber.fixLeak(myHouse.bathroom.leak) // =(

"

from this point on, the remaining OOP concepts where easy to explain.

Harima555
+2  A: 

Understanding interfaces is not very different to understanding polymorphism and IS-A relationships. All classes implementing the same interface can be manipulated uniformly by the program as the "base" type because of the relationship established by implementing an interface or inheriting a base class.

The choice between an interface and a base class is a design decision. I'd keep this simple.

  • Define a class when your implementation can assume the complete or partial behavior of a class.
  • Make that class abstract to indicate the base class is not a complete implementation and cannot be used as is.
  • Provide an interface instead of a base class if it does not make sense to provide a partial implementation.

The benefits of interfaces and inheritance are pretty much the same. An interface is simply a more abstract definition of a type than a base class is.

Update

Here's a simple program you could use to demonstrate how similar inheritance and interfaces are. Modify the program to make Base an interface instead of a class. In ClassA, replace "extends" for "implements". The program's result will be the same.

The purpose of ClassB is to illustrate further illustrate the importance of the relationship between a class and its interface/base class. An instance of ClassB may not be passed to processBase in spite of its similarities with Base, unless we establish an explicit relationship.

abstract class Base {
  public void behavior() {};
};

class ClassA extends Base {
  public void behavior() {
    System.out.println("ClassA implementation of Base behavior");
  }
};

class ClassB {
  public void behavior() {
    System.out.println("ClassB's version of behavior");    
  }
}

public class InterfaceExample {

  public void processBase (Base i) {
    i.behavior();
  }

  public static void main (String args[]) {
      InterfaceExample example = new InterfaceExample();
      example.processBase(new ClassA());
  }   
}
Philippe A.
This answer is technically sound, but otherwise rubbish. Many students will be frightened by your explanation. The goal is to explain what an interface using terms and concepts the student already understands. If the student is already comfortable with polymorphism, then the student probably does not need your lesson on interfaces.
emory
@emory, you don't get the implicit idea that in a Java course inheritance is probably covered before interfaces (imo it should). Once students have worked on inheritance and understood it, that material should be used to teach them interfaces. If they don't understand inheritance, they won't understand interfaces. So maybe a part of the problem is that inheritance is not clear enough to students when they get to interfaces.
Philippe A.
A: 

A long time ago, I read a book (can't remember the name of it though) and it had a pretty good analogy for interfaces. If you (or your students) ever went to a Cold Stone Creamery ice cream store, this will sound kind of familiar. Cold Stone has ice cream and with the ice cream you can add several different things to the ice cream (called mix-ins at Cold Stone). These mix-ins would be analogous to interfaces. Your class (or ice cream) can have as many interfaces (or mix-ins) as you want. Adding an interface (or mix-in) will add the contents (or flavor) of that interface (or mix-in) to your class (or ice cream). Hope this helps!

icemanind
A: 

Contracts are first things that are taught about interfaces but they are built in the language to provide the skills of multiple inheritance and avoid the complexity of multiple inheritance.. So you can teach them that interfaces add runtime behaviour to programs, or you can tell the students that interfaces can be used to change runtime behaviour of objects..

LostMohican
A: 

First, the students must grasp the concept of abstractions. When you (you == the students) see a teacher, you can describe him as a teacher... You can also describe him as an employe (of the school). And you can describe him as a person. You will be right the three times. Thoses are "titles" you can give him.

He is a teacher, a computer science teacher, in the same way a math teacher is a teacher. They are on the same level of abstraction. Now a teacher is an employee, in the same way a janitor is an employee. They are on the same level of abstraction. An employe is a person, in the same way an unemployed person is a person. They are on the same level of abstraction.

(Draw the whole thing on the board in a UML kinda way).

And that's the architecture that will describe (roughly) the position of a science teacher in society.

Now the levels of abstraction define what a common group of objects have in common : All the teachers teach to their students and create impossible exam questions to make sure they fail. All the school's employes work for the school.

In programming, an interface is a level of abstraction. It describes the actions that a group of objects can accomplish. Each object has a unique way of doing the action, but the type of action is the same.

Take a few music instruments for example : A piano, a guitar and a flute. What do they have in common ? A musician can play them. You can't ask a musician to blow in the 3 instruments but you can ask him to play them.

The architecture of the whole concept will be the following:

The Interface (what they have in common) is Instrument. Because they're all instruments : it's an abstraction they all have in common. What can they do in common ? Play. So you define an abstract method called Play.

Now you can't define how the "Instrument" will play because it depends on the type of instrument. Flute is a type of Instrument. So the class Flute implements Instrument. Now you must define what the musician will do when he plays that type of instrument. So you define the play method. This definition will override the definition of the Instrument. Do the same with the 2 others instruments.

Now if you have a list of instruments but don't know what type they are, you can still "ask" them to play. Each flute will be blown. Each guitar will be scratched. Each pianio will be ... huh... pianoted ? whatever !

But each object will know what to do to execute the action "Play". You don't know what kind of instrument they are, but since you know they are instruments, you ask them to play and they know how to do that.

Silence
I could also link to the explanation of abstract classes easily.
Silence
A: 

Well, I found lately a very useful method of using interface.

We have many objects...

public class Settings { String[] keys; int values; }
public class Car { Engine engine; int value; }
public class Surface { int power; int elseInt; }
// and maaany more (dozens...)

Now, someone is creating (i.e.) table and want to show some of objects from the list of all objects, but to show objects in the list he must write method that returns String[].

String[] toArrayString()

So he just implements this method in all classes that he need to in table

public class Settings { String[] keys; int values; public String[] toArrayString {...} }
public class Car { Engine engine; int value; } // THIS NOT
public class Surface { int power; int elseInt; public String[] toArrayString {...} }
// and maaany more (dozens...)

Now, when he creates table he is writing smth like this

public void createTable() {
    for(Object obj : allObjects) {
       if(obj instanceof Settings) {
          Settings settings = (Settings)obj;
          table.add(settings.toArrayString());
       }
       if(obj instanceof Surface) {
          // cast...
       }
       // etc multiple times...
    }
}

With interface this code can be much shorter and easier to read and maintain:

public interface ISimpleInterface { String[] toArrayString; }

public class Settings implements ISimpleInterface { String[] keys; int values; public String[] toArrayString {...} }
public class Car { Engine engine; int value; } // THIS NOT
public class Surface implements ISimpleInterface { int power; int elseInt; public String[] toArrayString {...} }

public void createTable() {
    for(Object obj : allObjects) {
       if(obj instanceof ISimpleInterface) {
          ISimpleInterface simple = (ISimpleInterface)obj;
          table.add(simple.toArrayString());
       }
    }
}

Moreover, we can implement multiple interfaces in a very clean and effective way without any derivation (derivation is sometimes impossible and not only in case, when class is using some kind of other derivation already).

Mouster
A: 

You may also want to compare and contrast interfaces in Java with C++ (where you end up using multiple inheritance and/or "friend" classes).

(At least, to me, that showed me how much simpler/easier interfaces were in Java :-)

Eno
A: 

I would tell them "Interfaces define what behaviors are provided" and "Implementations provide those behaviors". A piece of code that uses an interface doesn't need the details of how things are happening, it only needs to know what things can happen.

A good example is the DAO pattern. It defines behavior like "save", "load", "delete". You could have an implementation that works with a DB, and an implementation that goes to the file system.

I think a lot of the other answers so far are too complicated for students who don't get it right away...

hvgotcodes
+6  A: 

Class, we spent the last few sessions implementing quicksort. It was difficult to sort that list of Persons by name. What would you now do, if you had to sort this list by grade? And what would you do if you had to sort a list of dinousaurs by age? The only way you know so far is to copy the code of the quicksort, and change the comparison and the types it operates on. That would work - until you find that elusive bug that always plagued your quicksort, and had to fix it in several dozen copies of that quicksort scattered all over the place.

Today, we are going to learn a better way.

We can write a quicksort without defining the order we want to sort the list into, and define that order (and only that order) separately when we invoke that quicksort.

[ insert explanation of the mechanics of interfaces and polymorphism, using the Comparator interface as example, here ]

Now, there is only a single copy of quicksort, and bugs only have to be fixed once. Also, people can use quicksort without understanding it (or if they have understood it, without thinking about its mechanics whenever you want to sort something). Also, the people writing the quicksort did not need to know the order you need your list sorted. So the interface isolated the two groups of programmers, allowing them to develop their parts of the software in isolation. This is why, in many programming languages, you will find well implemented and tested sort methods in the api, even though the programmers of these methods could not know all the types of objects and orders people want to sort into later.

meriton
Great idea to explain in terms of standard library level functionality. Students are likely to be already familiar with these objects and just need to be shown how the specifics.The example I was thinking of was writing a program with a List so you can easily switch from ArrayList to LinkedList, etc...
pydave
A: 

I think in general, hands-on learning always helps reinforce concepts after lectures and examples. So in the same vein as meriton suggests, I would present two versions of the same program. (quicksort is a good example)

Have the students modify each program several times, unveil subtle bugs in the program for them to fix. Your students will soon find, I think, that interfaces provide many advantages when designing a program when they're the ones who have to modify it later!

weiy
A: 

I always think of it as a mean to (verbally) communicate as little as possible because that (good communication) is the most difficult thing in software engineering. Same for Web Services and SOA. If you give somebody an interface and say "Please provide me this service." it is a very convenient way because you don't have to explain a lot, and the compiler will check if they did a proper job, instead of you! (I mean, not really but at least it'll ensure the methods are there).

Enno Shioji
A: 

Interface Oriented Design describes this better than I ever could http://pragprog.com/titles/kpiod/interface-oriented-design. The author uses some excellent examples of interfaces versus inheritance for things like the taxonomy of the animal kingdom. It has some of the best arguments against excessive inheritance and judicious use of interfaces I have read to date.

A bunch of websites with incompatible ways of bringing them up:

Listing of Facebook.java:

public class Facebook {
    public void showFacebook() {
        // ...
    }
}

Listing of YouTube.java:

public class YouTube {
    public void showYouTube() {
        // ...
    }
}

Listing of StackOverflow.java:

public class StackOverflow {
    public void showStackOverflow() {
        // ...
    }
}

A client manually handling the different methods the websites use to bring themselves up:

Listing of ClientWithoutInterface.java:

public class ClientWithoutInterface {
    public static void main(String... args) {
        String websiteRequested = args[0];
        if ("facebook".equals(websiteRequested)) {
            new Facebook().showFacebook();
        } else if ("youtube".equals(websiteRequested)) {
            new YouTube().showYouTube();
        } else if ("stackoverflow".equals(websiteRequested)) {
            new StackOverflow().showStackOverflow();
        }
    }
}

Introduce a Website interface to make the client's job easier:

Listing of Website.java:

public interface Website {
    void showWebsite();
}

Listing of Facebook.java:

public class Facebook implements Website {
    public void showWebsite() {
        // ...
    }
}

Listing of YouTube.java:

public class YouTube implements Website {
    public void showWebsite() {
        // ...
    }
}

Listing of StackOverflow.java:

public class StackOverflow implements Website {
    public void showWebsite() {
        // ...
    }
}

Listing of ClientWithInterface.java:

public class ClientWithInterface {
    public static void main(String... args) {
        String websiteRequested = args[0];
        Website website;
        if ("facebook".equals(websiteRequested)) {
            website = new Facebook();
        } else if ("youtube".equals(websiteRequested)) {
            website = new YouTube();
        } else if ("stackoverflow".equals(websiteRequested)) {
            website = new StackOverflow();
        }
        website.showWebsite();
    }
}

Whoop-de-doo, more code for nothing? Actually we can go a little further and have the client rope a couple of friends into helping it find and render a requested website:

Listing of ClientWithALittleHelpFromFriends.java:

public class ClientWithALittleHelpFromFriends {
    public static void main(String... args) {
        WebsiteFinder finder = new WebsiteFinder();
        WebsiteRenderer renderer = new WebsiteRenderer();
        renderer.render(finder.findWebsite(args[0]));
    }
}

Listing of WebsiteFinder.java:

public class WebsiteFinder {
    public Website findWebsite(String websiteRequested) {
        if ("facebook".equals(websiteRequested)) {
            return new Facebook();
        } else if ("youtube".equals(websiteRequested)) {
            return new YouTube();
        } else if ("stackoverflow".equals(websiteRequested)) {
            return new StackOverflow();
        }
    }
}

Listing of WebsiteRenderer.java:

public class WebsiteRenderer {
    public void render(Website website) {
        website.showWebsite();
    }
}

Looking back at ClientWithoutInterface, it is totally coupled to both specific lookup and rendering based. It would be very difficult to manage when you get to hundreds or thousands of sites. With the Website interface in place the WebsiteFinder could easily be converted to be backed on a Map, a database or even a web based lookup to satisfy increasing scale.

Interfaces make it possible to separate a role from the component that achieves it. They make it possible to swap in alternative solutions to the same problem based on pretty much anything:

  • Current load on machine

  • Size of the data set (sorting algorithms can be picked)

  • User requesting the action being performed

Alain O'Dea
A: 

I was typing this as a comment to Harima555s answer, but it expanded. I wondered if it makes more sense to start at the other end - give them a feel for how interfaces are useful, before going into how you write one.

Presuming they have a good grasp of inheritance, polymorphism and abstract classes. I would probably start with a recap on abstract classes, by asking one of the students to explain them.

Next, introduce an example of classes with interfaces to get over the concept of roles / contracts. To simplify things, start with a single superclass.

public class Rick extends Person implements SoftwareDeveloper, Plumber
public class Zoe  extends Person implements SoftwareDeveloper, Chef
public class Paul extends Person implements Plumber, Chef
public class Lisa extends Person implements Plumber

Don't explain it too much, but try and get the student to work through what the syntax might mean - perhaps showing some code that references a Plumber or SoftwareDeveloper.

Ask them how they would achieve the same thing using inheritance from Person. They should get stuck quite quickly, or come up with multiple inheritance. To avoid discussing the diamond problem until later, say there are no overlapping methods in the roles.

Next I'd try to get over the idea that the same interface can be used on different types of Class.

public class Plane extends Vehicle implements Fly, PassengerTransport, Serviceable
public class Train extends Vehicle implements PassengerTransport, Serviceable
public class Bird  extends Animal  implements Fly

Again, try to get them to consider how they could implement the same thing using a common superclass and overrides.

Then illustrate how you would write polymorphic code using the interface rather than class - say a TravelAgent who sells tickets for a PassengerTransport. Dwell on the strength of this - that you can write polymorphic code that works on Classes from different hierarchies.

At this point, they should probably be under the illusion that an interface is a pretty much like being able to add another superclass to a class, and will have grasped the advantages of multiple inheritance.

So now we have to explain why that complicates things, and interfaces have no default implementation, via understanding the diamond problem.

Go back to the first example, get them to work through what happens if SoftwareDeveloper and Plumber both have a 'MakeDrink' method (one makes Cola, the other makes Coffee) and we execute MakeDrink on Rick.

Try and nudge someone towards considering the idea that if MakeDrink is kept abstract in both 'superclasses' the problem goes away. At this point, having got the conceptual side, we should be ready to cover the syntax for defining an interface.

(I did consider introducing the second reason - the difficulty of writing generic code that could be applied to different class hierarchies, but found that you end up with 'well why can't you inherit an altitude attribute from the interface' or discussing generic programming too early).

I think by now we should have covered the concepts via the mickey mouse examples - and you could then go back through explaining the correct technical terminology, and use real-world examples from the Java API.

  • I wouldn't want to confuse people while they are trying to learn Java/Interfaces, but once they've got it, it may be worth pointing out that other OO languages take different approaches to the same problem, from multiple inheritance to duck-typing - and if they are interested they should research them.
JulesLt