In J2SE5 (at least) you can even define variables in
interfaces.
Only constants, not variables.
My question, then, is why would anybody ever use an interface as
opposed to abstract classes? Surely there must be some benifit to
using interfaces in some scenarios, I am just not sure what it is.
Here's another view on the topic.
Let's forget about abstract classes for a minute, and consider the difference
between interfaces and concrete classes.
Imagine that you are going to buy a new car. As a potential customer, you
might say:
The car must be red.
(Assuming you like red...). A delivery person might say:
The car is red.
The two sentences are /very/ similar, but they mean /very/ different (but not
unrelated) things. The similarity/difference is closely akin to the
similarity/difference between interfaces and classes. More specifically it is
akin to the difference between what looks like a method (with no body) in an
interface, and an actual method in a class.
In the case of the car you set a requirement which the car sales organisation
has to meet. If the salesthing had said:
The car will be red.
then that would be a promise to you. That pairing of a promise/requirement
forms a contract (probably not one that would stand up in law -- but that's a
different matter). You have made an agreement. Interfaces are the same, they
state conditions on the objects which will be used in certain contexts. If I'm
creating a farm simulation, and you are going to be supplying animals to live
in it, then I might define a contract stating what properties/behaviours your
objects must have before I would allow them as animals on my farm.
// the contract
interface FarmInhabitant
{
void eat();
void sleep();
void shit();
void die();
}
class Farm
{
// before you can use my Farm, you have to sign up to the contract.
// Only objects which act as FarmInhabitants are allowed
addInhabitant(FarmInhabitant it) { ... }
}
As you'll see the contract isn't very expressive -- there's no way I can say
"must not make loud noises all night", "must not tear arms and legs off passing
humans", or "must be tasty and large enough to be worth eating". Some
programming languages attempt to beef up (sorry) the contract language so it
can express more; Java keeps it simple and you are limited to listing the
methods which must be available. Anyway. With that contract defined, you can
create your animals, and pass them to my farm. Your code might follow the
classical OO example:
Cow
IS-A Mammal
IS-A Vertebrate
IS-A Animal
IS-A Eukaryote
IS-A CarbonBasedLifeForm
I (or my farm) just don't care. It's none of my business how you structure
your code. All I care about is that you stick to our contract. In this case
that means that if you want to pass Cows to addInhabitant() then Cow had better
declare that it will meat (sorry) the terms of the contract. I.e. it should
say:
class Cow
extends Mammal
implements FarmInhabitant
{
....
}
And if you do that, the contract even has something like the force of law,
since the compiler won't let you declare that you meet the terms of the
contract unless you actually do (i.e. there are real methods I can call, with
names eat(), sleep(), etc). And if you /do/ meet the terms, then the compiler
won't let me /refuse/ to accept your Cows (I can throw exceptions, but I can't
stop you calling the method in the first place). If someone else wants to use
my farm too, then they might have a completely different set of classes to
create animals (perhaps their Sheep are assembled from a collection of Legs,
Heads, Tails, etc. rather than being a descendant of a deep class hierarchy).
Again, as long as Sheep meet the terms of the FarmInhabitant contract, then
they can be added to my farm. Perhaps even the same farm as your Cows.
Interfaces can also be used the other way around. Not as a requirement, but as
a promise. I can't think of a way to extend the farm example to illustrate
that, but it's probably obvious anyway once you've started to think of
interfaces as contracts.
So an interface defines the contract between the supplier of an object and the
user of that object.
BTW: You can also think of interfaces in a slightly weaker way -- as a way of
/describing/ classes. That brings out the difference between classes and
interfaces rather nicely -- the thing is not the same as the description -- but
since the Java compiler and type system get in on the act, it's probably better
to stick with thinking of interfaces as contracts.
Let's take an aside into "multiple-inheritance". Some people like to say that
Java has multiple inheritance of interfaces. That's technically true, but I
think it misses the point entirely -- and is highly misleading. Going back to
our car example. If I had signed some sort of contract to buy a car, it would
be absurd if I couldn't then buy a house, or take a new job. Yet that's
exactly what would happen if I were only ever allowed to sign one contract. I
can agree to as many contracts as I like (always supposing their terms are
mutually consistent). So why is that like multiple inheritance ? Answer: it
isn't like multiple inheritance at all ! (Yes, it is possible for one
contract to refer to another -- "by agreeing to these terms and conditions, you
also agree to abide by the terms and conditions set out in <such-and-such>" --
and that is much more like inheritance. So there is a sort of inheritance
network between contracts. But that doesn't make it any less absurd to say
that if I have signed two contracts, then I have "multiply inherited" them.)
OK, now we have -- I hope -- a clear picture of the way that interfaces and
classes are totally different kinds of entities, despite their syntactic
similarity. (Recall the syntactic similarity of the two sentences about red
cars). They are not even at the same level -- interfaces are /about/ classes,
rather than being a /variant of/ classes.
So what of abstract classes ? This is where the picture becomes a little
confused, because the Java language design is itself a little confused. The
simple answer is that there shouldn't be any abstract classes in their current
form -- which would completely remove the opportunity for confusion ;-) The
question here is: what do the abstract methods in an abstract class mean ?
What are they for ? And the problem is that, the way Java is designed, there
are two possible answers (depending on the design of the class).
One answer is perfectly legitimate (IMO, although some might disagree). In
this case the abstract class has been designed as a sort of framework or
template, and the abstract methods are there to tell sub-class implementers
what details they are expected to fill in. That is a perfectly reasonable way
of designing frameworks, and abstract methods are a perfectly reasonable way of
expressing that design. It might be better if "abstract" methods were never
public, and could only be called from the superclass, but that's not the way
Java is designed. What we have works well enough in practice (and anyway, we
can always follow the extra restrictions voluntarily even though the compiler
doesn't enforce them).
You'll notice that that use of abstract methods has little in common with the
idea of interfaces as contracts. There is /some/ similarity, but they are
being used much more like the instructions that come in the box with
self-assembly furniture, than like a legal agreement.
Its the other answer which causes problems. Up till this point, we had
complete clarity. Interfaces and classes do different things. Abstract
methods in abstract classes mean something almost entirely unlike the "abstract
methods" in interfaces. But now we get to the place where Java screws up.
Abstract methods can /also/ be used in a sort of interface-y way, as an
explicit promise from a superclass, to users of its subclasses, that those
subclasses will have certain methods, even though it itself doesn't have them.
To my mind, that's just confused. There is no need for the feature since the
superclass could just sign up to the relevant contract (implement the relevant
interface), but not satisfy the terms itself -- thus leaving subclasses to
inherit an obligation which they would have to satisfy. Why the Java designers
choose to muddy the waters like this, I don't know. It may have been intended
to reduce the verbosity of the language, i.e. as an abbreviation for defining
an explicit extra interface and signing up to it. It might be that they were
worried about efficiency. Both those have something to be said for them, but
the gains are small, and the downside is that two concepts which /should/ be
totally, unmistakably, distinct have been muddled together.
There are also some technical limitations of using abstract classes this way
(other people have already described them clearly), but my point is that it
would still be a bad idea even if those limitations were removed, or if didn't
matter in some specific application.
To sum up. Interfaces are for defining contracts. Abstract classes are for
creating frameworks (and the abstract methods should usually be protected).
Abstract classes /can/ also be used to define contracts too, but that's in poor
taste, so we never do it ;-)
-- chris