To resurrect an old example - let's try Cars.
Say that I happen to work for the automotive industry
and we are just getting into the
Java coding business. However I want to leverage my code across lots of applications in the Division.
I know that we are eventually going to do LOTS of stuff with Car objects, and I want to make sure that
we all work in unison.
So I make an interface called Car and in that interface I define all of the things that I want to make SURE that every thing that implements Car takes care of. So I put empty methods for Steering(), Break(), StartEngine(), Slowing(), WipeWindsheilds() and OpenDoor() etc. Every one in the department knows the methods that Car
must do. It's all defined in the Interface. And, yes, we DO insist that all cars can Steer etc.
Now I make
abstract class Sedan implements Car{ }
abstract class Coupe implements Car{ }
abstract class Convertible implements Car{ } etc.
We all know that these classes have identical methods from Car and we know how to use them. Plus they may have their own methods - like Convertible may have a method OpenRoof() that Sedan does not have.
They must have the methods of the interface but maybe not ALL those methods are implemented (yet). Even if they were, you can not really build a Sedan, you have to build a specific model of a Sedan (like a Buick or a Cadillac). So I made the class abstract to prevent someone trying to make an instance of it. Eventually when the Buick class is created it will inherit all of the implemented methods that Car insisted on and all of the implemented methods that Sedan added, and Buick may have to add it's own implementation for any abstract methods that I may have left in Sedan. So extending the abstract class is a bit easier in that I don't HAVE to implement every one of those pesky methods, however it adds the danger of "typoing". With an interface you
have to implement each and every method (and SPELL it correctly or the compiler complains). When sub-classing if you try to override a method and mis-spell it, it just becomes an additional method and the original method is still there and active - no compiler to give you a clue.
Anyway - back to interfaces:
I can now make "generic variables".
Cadillac c = new Cadillac();
Buick b = new Buick();
Car someCar = b;
someCar = c;
The someCar variable can hold any class that implements Car and we KNOW that it will be able to DO any of the methods defined in the Car interface. So now I can call someCar.StartEngine() even though I do NOT know what exact TYPE of car is being held in the someCar variable. I know because of that "service contract" that Junilu was talking about, the agreement that all cars would have this set of methods.