Interfaces are about setting a contract, an agreement. When a class implements an interface, it agrees to meet the contract set out by that interface. Interfaces are about defining what operations are available. Classes (including abstract classes), on the other hand, are not *just* about defining what operations are available, but also *how* those operations are carried out.
Here is a very trivial example that you may find instructive. If I am interested in defining an operation increment(), and I know that most subclasses will vary in the way they choose to implement that increment(), I should put it in an interface. Using an interface, I am simply saying that implementing classes will take these arguments and return this result, without regard for how this operation is carried out.
If I am defining an increment() operation, and I know that most if not all subclasses not only want this operation *defined*, but also would like the *means by which it is carried out* defined, then I would put it in an abstract class.
What about a "pure" abstract class, with no method implementations, only abstract methods? Is there a difference between this and an interface (besides the obvious restriction that Java only allows a class to extend one class, whereas it can implement many interfaces)?
Yes. When you write a "pure" abstract class, this is a statement about future maintenance. When you choose an abstract class in this case, you are saying, "I don't have any implementation right now that subclasses would be interested in, but as this project evolves and new versions are released, if ever one of these methods are made concrete subclasses will mostly be interested in those implementations."
This is a very rare circumstance, but it does happen. Most of the time, it is appropriate to prefer interfaces to classes. This is because an interface is the only way to nail down some aspect of a design without regard for implementation details. This is very important to do, and it is also important to nail down these aspects of design using interfaces because you're putting a stake in the ground saying, "This is an aspect of the design on which the evolution of the project hinges." By writing an interface, you are effectively fixing this contract as a long-term part of the design. If you write a good design and fix all the right aspects of it, you can make sure you are writing an extensible, flexible system.
For example, let's say you're designing a geometry package. You might think it's a good idea to have an abstract Shape class, and have Rectangle, Trapezoid, etc, extend that class. There are several things
you should be able to do to anything that calls itself a "shape": get the length around the perimeter, rotate it about its center, get the number of sides, etc. If you write Shape as an abstract class, you might find that you can provide default implementations of these methods that "kind of" make sense...but by providing implementations you could be fixing points of your design that should remain open. If you choose to simply mark these methods as abstract, you are saying that these points are open for now, but in a future version they may not be. This unwillingness to nail down this aspect of the design forms a shaky foundation. Classes that do extend Shape are depending upon a class that is open to changing in any way that a class can over several versions of evolution. It is generally bad to set up a large base of code that is dependent on an unstable foundation.
So, instead, write Shape as an interface and all you have to do is define the operations. Classes that implement this interface can be guaranteed that it will remain relatively stable because interfaces cannot undergo many of the changes that classes can as projects evolve. A stake is in the ground that fixes in your project what it means to be a shape, and fixes it in a way that is unchangable.
In some cases you will find the need for both...you'll want several classes to get the advantages of implementing an interface, but at the same time they do have code that is likely to be the same. No sense in repeating it:
In the above code sample, you can see how the getNumPoints() code is shared amongst all of the concrete shapes (circle, square) without each having to rewrite that code. Plus, you can see how all of the advantages of having Shape expressed as an interface is intact--no outside code can depend on AbstractShape because the class is marked protected. Only subclasses even know about its existence (and classes in the same package, but presumably those are written by the same developer as the AbstractShape class itself, and he would know better than to have a reference of that type floating around in his own code).
So, any outside code that wants to refer to Circle and Square objects polymorphically has no choice but to refer to them as Shapes, yet they still get the benefit of inherited code. The drawback--these two classes, because they extend AbstractShape, must agree that they are primarily AbstractShapes implementation-wise. They are unable to extend another class. This is a mild drawback at best, though, because if you think about it, it's a trivial thing to have a class that doesn't want the numPoint code to simply implement Shape directly, write its own version of that code (if it's not using AbstractShape's implementation, than it wouldn't want to share that code anyway), and then it can inherit implementation from whatever other place it wants.
In summary...the simple answer to your question that I've found most interviewers look for is: In Java, a class can only extend one other class, but it can implement many interfaces. That is obviously correct, but doesn't get at the heart of the matter--it simply begs the question, "Why did the designers of Java make that decision?"
The more complicated answer is: when a class extends another class, a statement is made that the subclass will want the superclass' *implementation* on an ongoing basis. If that superclass' code changes for a future version, it is expected that *all* subclasses will want that change. When a class implements an interface, the statement being made is different; the subclass is simply agreeing to deliver a certain result if the conditions specified by the interface are met by the caller.
sev