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.
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.
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.
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:
Listing of YouTube.java:
Listing of StackOverflow.java:
A client manually handling the different methods the websites use to bring themselves up:
Listing of ClientWithoutInterface.java:
Introduce a Website interface to make the client's job easier:
Listing of Website.java:
Listing of Facebook.java:
Listing of YouTube.java:
Listing of StackOverflow.java:
Listing of ClientWithInterface.java:
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:
Listing of WebsiteFinder.java:
Listing of WebsiteRenderer.java:
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
Well, I found lately a very useful method of using interface.
We have many objects...
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[].
So he just implements this method in all classes that he need to in table
Now, when he creates table he is writing smth like this
With interface this code can be much shorter and easier to read and maintain:
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).
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!
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.