There are two good reasons to learn the meaning of polymorphism. First, using such a
fancy word in casual conversation makes you sound intelligent. Second, polymorphism provides one of the
most useful programming techniques of the object-oriented paradigm.
Polymorphism, which
etymologically means "many forms," is the ability to treat an object of any subclass of a base class as if it
were an object of the base class. A base class has, therefore, many forms: the base class itself, and any of
its subclasses.

If you need to write code that deals with a family of types, the code can ignore type-specific details
and just interact with the base type of the family. Even though the code thinks it is sending messages to an
object of the base class, the object's class could actually be the base class or any one of its subclasses. This
makes your code easier for you to write and easier for others to understand. It also makes your code
extensible, because other subclasses could be added later to the family of types, and objects of those new
subclasses would also work with the existing code.

To see how to use polymorphism in a Java program, consider the family of types shown in Figure 8-1.
To use an object of type Liquid, you must create a Liquid object
with new and store the returned reference in a variable:

Liquid myFavoriteBeverage = new Liquid();

The myFavoriteBeverage variable holds a reference to a
Liquid object. This is a sensible arrangement; however, there is another possibility
brought to you courtesy of polymorphism. Because of polymorphism, you can assign a reference to any
object that is-aLiquid to a variable of type Liquid.
So, assuming the inheritance hierarchy shown in Figure 8-1, either of the following assignments will also
work:

Therefore, you can sprinkle some polymorphism in your Java program simply by using a variable with a
base type to hold a reference to an object of a derived type.

Figure 8-1. The Liquid Family

To get the full benefit of polymorphism in your programs, however, you'll need to go further. To fully
realize the wonders of polymorphism, you must send a message to an object without knowing the actual
class of the object. To do this in Java, you just invoke a method defined in a base type on an object
referenced by a variable of the base type. As you saw above, the object referred to by a base class reference
might be of the base class or any of its subclasses. Therefore, when you write the code to invoke the
method, you don't necessarily know the actual class of the object. Likewise, when you compile the code,
the compiler doesn't necessarily know the actual class of the object. At run-time, the Java Virtual
Machine determines the actual class of the object each time the method invocation is requested by your
program. Based on this information, the Java Virtual Machine invokes the method implementation
belonging to the object's actual class. Letting the Java Virtual Machine determine which method
implementation to invoke, based on the actual class of the object, is how you realize the full power of
polymorphism in your programs.

As an example, consider the family of types for Liquid shown in Figure 8-1.
Assume the base class, Liquid, defines a method swirl()
which takes a boolean parameter clockwise. When
swirl() is invoked on a Liquid object, the object simulates a
swirling motion. If the clockwise parameter is true, the
Liquid object swirls clockwise. Otherwise, the Liquid object
swirls counterclockwise. Assume also that the subclasses Coffee and
Milk override the default implementation of swirl() to account
for the unique viscosity of those specific kinds of Liquid. Milk,
for instance, might swirl more slowly because it is thicker. This arrangement can be expressed in Java
code as follows:

To carry the example further, take another look at the addLiquid() method of
the Cup family of types shown in Figure 8-1. Assume class Cup
defines an addLiquid()method that you have overridden in class
CoffeeCup, much like the example on the right hand side of Figure 7-2. In the right
hand version of Figure 7-2, class CoffeeCup overrides
addLiquid() so that the liquid can be made to swirl counterclockwise as it is added
to the cup. Now that you have a Liquid class with an actual
swirl() method, you could implement the addLiquid()
method in CoffeeCup as follows:

Given the above definition of CoffeeCup, you can reap the benefit of
polymorphism by invoking addLiquid() with different kinds of liquid:

// In Source Packet in file inherit/ex2/Example2.java
class Example2 {
public static void main(String[] args) {
// First you need a coffee cup
CoffeeCup myCup = new CoffeeCup();
// Next you need various kinds of liquid
Liquid genericLiquid = new Liquid();
Coffee coffee = new Coffee();
Milk milk = new Milk();
// Now you can add the different liquids to the cup
myCup.addLiquid(genericLiquid);
myCup.addLiquid(coffee);
myCup.addLiquid(milk);
}
}

Note that the definition of addLiquid() treats the object passed in as a
parameter as if it is of type Liquid, yet the code above passes types
Coffee and Milk as well as Liquid. The
code of the addLiquid() method, therefore, doesn't know the exact class of the
object it is being passed. When swirl() is invoked on the object at run-time, the
implementation of swirl() that gets executed depends upon the actual class of the
object. In the first case, when genericLiquid is passed,
Liquid's implementation of swirl() will be executed. When
coffee is passed, Coffee's implementation of
swirl() will be executed. In the last case, when milk is passed,
Milk's implementation of swirl() will be executed.

Therefore, when milk is added to the cup, it will swirl like milk. When coffee is added, it will swirl
like coffee. All this is accomplished even though the code of the addLiquid()
method does not know the actual class of the object passed. This is the beauty of polymorphism.

Had you not known about polymorphism, you might have designed the Liquid
family and the addLiquid() method differently. Instead of taking advantage of
polymorphism's ability to figure out which method to call, you could have used a brute force method:

The creation of if-else constructs like the one shown above are possible in Java
because of the instanceof operator, which allows you to check whether an object is
an instance of a certain class. Here the instanceof operator is being abused, and
the code should be reorganized to use polymorphism. The instanceof operator, and
the situations in which it should be used, will be discussed later in this chapter.

The above code is more difficult to read and less extensible than the code (shown earlier) that took full
advantage of polymorphism. If later you added a new type to the Liquid family, say
Tea, you would have to add another if-else statement to the
above code. You would not, however, need to make any changes to the earlier
addLiquid() implementation that took advantage of polymorphism. That
implementation of addLiquid() would still work, even though you wrote it before
you knew about Tea. Whenever you find yourself writing a series of if-
else statements, where the condition is a test of type, you should try and see if your program
can't be redesigned to take advantage of polymorphism.

Programming down the path of polymorphism implies that you write code that lets an object figure
out how it should behave. In the previous example, you told an object to swirl, and expected it to swirl in
the manner objects of its class are supposed to swirl. You didn't tell it explicitly whether it should swirl
like milk or coffee, you just told it to swirl. If the object was actually milk, you expected it to behave like
milk and swirl in a milky way. This attitude towards objects fits well with the object-oriented mindset,
because the customary mission of a method is to manipulate the internal data of the object. Objects are
supposed to know best how to manipulate their own data, which is the reason data is usually
private. Keeping data private gives full responsibility for
proper manipulation of the internal state of an object to the object's methods. Polymorphism gives you
another way in which you can give objects responsibility for their own behavior--the object's behavior
matches its class.

Static versus Dynamic Binding

The underlying mechanism that makes polymorphism possible is dynamic binding.
Except for three special cases, all instance methods in Java programs are dynamically bound. The instance
method that is invoked at run-time will be determined by the actual class of the object, not by the type of
the reference. This differs from C++, in which you must declare an instance method
virtual to get polymorphism and dynamic binding. If you don't declare an instance
method virtual in a C++ class, you get static binding, in which the
method called is determined by the type of the reference, not the class of the object referred to by the
reference. Polymorphism plays no role in static binding. In C++, therefore, a programmer can, wielding
the power of the virtual keyword, create instance methods that are either statically
or dynamically bound. In Java, however, "virtual" is not a keyword, and all
instance methods, except for the three special cases, are dynamically bound. The three special cases are
private methods, instance method invocations with the super keyword, and
invocation of instance initialization methods. These cases will be described further later in this chapter.

Static binding also plays a role in class methods (those declared with the static
modifier), which are always statically bound. You can redefine a class method in a subclass, just like an
instance method; however, a redefined class method will not participate in the rewards of polymorphism
and dynamic binding. Because class methods do not operate on specific objects, you don't even need an
object to call them. Class methods can be invoked even when no instances of the class exist.
Polymorphism requires an object, because it enables a method to be dynamically selected based on the
actual class of the object. Thus, polymorphism does not apply to class methods. If you invoke a class
method on an object, the implementation of the class method is chosen based not on the class of the object
at run-time, but on the type of the object reference at compile-time.

For example, imagine you want to be able to simulate an earth tremor in your cafe, by sending a
message to all liquids in the cafe, telling the liquids to gurgle. The clientele of the cafe will know
something is happening when, as a result of the pan-liquid gurgle command, they see their coffees and
teas producing bubbles and generally sloshing about. One way you could model this in your Java program
is by declaring a static method, gurgle(), in the
Liquid class:

Suppose you also wish to model an unusual kind of earth tremor that affects only milk, but not any
other type of liquid. Perhaps the frequency of the tremor matches exactly the resonant frequency of milk,
so milk is the only liquid visibly affected. In this case you want to be able to send the gurgle command to
all milks, but not to any other liquids in the cafe. You could model this in your program by adding a
gurgle() method to the Milk class:

Armed with the implementations of Liquid and Milk shown
above, you are ready to have some fun. Assume you wish to start by simulating an earth tremor that
gurgles milk, but leaves all other liquids alone. Given your pleasant experience of polymorphism with
instance methods, you might try to accomplish the milk gurgling by code similar to the following:

The output generated by the above code demonstrates the statically linked nature of class method
invocations. In this code you have a reference of type Liquid, but an object of class
Milk. When you invoked swirl() on the object, polymorphism
came through for you, because Milk's implementation of
swirl() was executed. When you invoked gurgle(), however,
polymorphism abandoned you, and Liquid's implementation of
gurgle() was executed. The implementation of gurgle() to
invoke was determined statically at compile-time based on the reference's type
(Liquid), not dynamically at run-time based on the object's class
(Milk).

One way to solve the problem is to make sure you invoke gurgle() on a
Milk object being referred to by a reference of type Milk, as in:

This code generates the desired effect. One Milk object is swirled, and all
Milk objects are gurgled. The output generated by the above code is:

One Milk object is swirling.
All Milk objects are gurgling.

Yet even though you have gotten the results you want, you still haven't written code that clearly indicates
the class-wide nature of gurgle(). Most of the time, the best way to invoke a class
method is to use the class name, not a reference to an object of the class. For example, you could rewrite
the above code:

The line Milk.gurgle() more clearly indicates that a class method is
being invoked, and that polymorphism is not involved.

Redefining an instance method in a subclass is called "overriding" the instance method, however,
redefining a class method is not called "overriding." Instead, it is called hiding the class
method. The term "override" is associated with polymorphism, which doesn't apply to class methods.
Therefore, you can't override a class method, you can only hide it. For example, the
gurgle() method defined in Milk above hides the
gurgle() implementation defined in Liquid.

Because an invocation of a statically bound class method on an object looks similar to the invocation
of a dynamically bound instance method, you must be careful to always keep in mind the difference.
Invoking class methods using the class name, as in Milk.gurgle(), instead of an
object reference, as in m.gurgle(), is a good rule of thumb to help clarify your
code.

The this Reference

Point out using this for this.attr = attr, and mention
this is a kind of hiding. Talk about hiding in general, and make another request for private data.

The super Reference

Here talk about this, super, and ((SuperClass) var).memberName. Yes. This is where I can mention
the static binding of fields, because I show it with the (()) example. Whereas you could invoke a virtual
method in a superclass in C++ by using the scope resolution operator, in Java you can't access any
instance method that the current class overrides in any superclass other than your direct superclass. You
can do it with a field, whether its an instance or class variable, and with a class method simply by casting
the this reference to a superclass type.

Any field you declare private can't be hidden. If you favor private data in your class designs, field
hiding should be rare. You may occasionally encounter hiding with constant fields, which are often
declared public. You may also encounter field hiding when you use libraries that declare public fields.

One other justification for keeping data private is that fields are accessed not based on the class of the
object, but on the type of the reference. If a subclass hides a public instance variable of its superclass, then

[YIKES, DON'T I NEED TO TALK ABOUT STUFF FROM PAGE 61 OF JPL BOOK? FIELDS
ARE ACCESSED NOT BASED ON THE CLASS OF OBJECT, BUT THE TYPE OF THE
REFERENCE.]

Adding New Fields and Methods to a Subclass

The techniques discussed so far yield families of types in which all classes in the family have the
precisely same interface. A subclass can differentiate itself from all the other classes in the family by
overriding methods inherited from its direct superclass. In this very object-oriented scheme, a class that
belongs to a family of types expresses its uniqueness not by the interface it presents to the world, but by
the implementation underneath the interface. All the classes in a family might have a
swirl() method, for example, but each individual class might swirl in its own
unique way. This manner of modeling families of types is very expressive and allows you to take
advantage of polymorphism, but can sometimes restrict your ability to model the specific nature of a
subclass. Sometimes you may want a subclass to accept messages that its superclass does not accept. To do
this you must extend the inherited interface. You must add to the subclass new methods that did not exist
in the superclass.

Java allows you to define methods that enable a subclass to receive messages that would normally be
accepted only by the subclass, and not by a more general superclass. This muddies the object-oriented
metaphor a bit, because even though you can still substitute a subclass wherever a superclass is required,
the new methods you added to the subclass aren't accessible when you are treating the subclass as if it is a
superclass. For this reason, you will usually want to first attempt to design families of types in which
subclasses contain only methods that override methods inherited from superclasses. Sometimes, however,
you will feel the need to add new methods to subclasses. In those situations you must just live with the
inability to invoke one of the new methods when you have a reference to an object of the base type. You
will only be able to invoke the new methods when you have an explicit reference to the subclass type in
which the new methods are defined.

As an example, consider again the family of liquids. Up to this point you have been introduced to four
members of the liquid family, Liquid, the base class, and subclass siblings
Coffee, Milk, and Tea. Each of the
subclasses overrides the default implementation of swirl(), defined in base class
Liquid. So far every class in the family has the same interface, which is composed of
just two methods: swirl() and gurgle(). Now suppose you
want to be able to invoke a method on an object of class Tea that causes the object to
inspect itself, and from the configuration of tea leaves floating in itself, describe the future of the person
who is drinking the tea.

The ability to predict a person's future from the tea leaves left after they drink a cup of tea is not a
general property of liquids. It is a property only of tea. If you added a
readFuture() method to base class Liquid, that would imply
that one can see the future by peering into any liquid. But this is not true of coffee. It is not true of milk.
(It is probably not true of tea either, but for the sake of this illustration, assume it is.) Therefore, the best
way to model this in your design is to add a readFuture() method to the
Tea class only:

Given the design represented by the code above, you will not be able to call
readFuture() if you have a reference to an object of type
Liquid, even if the actual object being referenced is type Tea. As
demonstrated below, only if you have a reference of type Tea can you invoke the
readFuture() method:

// In Source Packet in file inherit/ex5/Example5a.java
class Example5a {
public static void main(String[] args) {
// Create a Tea reference and a Tea object
Tea tea = new Tea();
// Create a Liquid reference and, in the spirit of
// polymorphism, assign to it the same Tea object
Liquid liq = tea;
// Ask the tea object to read the future of its drinker
tea.readFuture();
// Attempt to ask the same tea object to read the future
// again, but this time via the reference to Liquid.
liq.readFuture(); // THIS WON'T COMPILE.
}
}

The example above demonstrates the consequence of adding new methods to subclasses. The new
methods can be called only when the type of the reference is the subclass. In this situation, however, it is a
reasonable way to model the fortune telling behavior of tea, and the consequences of the design are
acceptable.

When to Use instanceof

The fortune-telling behavior of Tea illustrates a situation in which you might want
to use instanceof. If you have a reference to a Liquid and you
want to swirl the liquid clockwise, you can use polymorphism because all liquids swirl:

The process of converting the Liquid reference into a Tea
reference is called "downcasting" because you are casting the reference "down" the inheritance hierarchy,
from Liquid to Tea. This illustrates the kind of situation in
which you should use instanceof. You have a base type reference, and if the object
referred to by the base type reference really is a certain subclass, you want to invoke a method that only
exists in that subclass.

Incidentally, Java ensures type-safety at run-time. If, for example, your program attempts at run-time
to downcast to Tea a Liquid reference that actually refers to a
Milk object, the Java Virtual Machine will throw a
ClassCastException. Each time a cast is performed, the actual class of the object
is checked to make sure the cast is valid.

Behind the Scenes

Statically Bound Instance Methods

When you invoke a private method from another method, both methods must be defined in the same
class. Although a method of the same signature as a private method can be declared in a subclass, a
private method can't be overridden by a subclass. When you invoke a private method, the Java compiler
knows precisely which class contains the method to invoke, because it must by definition be in the same
class. Static binding is used so that the private method is invoked independent of the actual class of the
object at run-time.

The super keyword, which will be described in detail later in this chapter, allows
you to access a superclass's methods and fields from a subclass, even if they are overridden or hidden in
the subclass. In the case of instance methods, static binding must be used. If a method is overridden in a
subclass, dynamic binding would cause the subclass's version of the method to be invoked rather than the
superclass's version. As with invocation of a private method, the compiler knows precisely which class
contains the method to invoke when it is invoked with the super keyword. Static
binding allows a superclass's version of an instance method to be invoked independent of the actual class
of the object at run-time.

The Java compiler creates one instance initialization method for each constructor in the
source for a class. This special kind of instance method is invoked only when an object is created. Like
private methods and methods invoked with super, instance initialization methods are
invoked using static binding. The details of this special kind of method will be described in Chapter 13.

For more information on static binding of instance methods, see the explanation of the
invokespecial instruction in Chapter 25.

Interfaces

As illustrated in the previous chapter, one of the most important benefits of class extension is that you
can take advantage of polymorphism. In an inheritance hierarchy, if class
CoffeeCup extends class Cup, you can treat a
CoffeeCup object as if it were a Cup object. Sometimes,
however, it is difficult to get the polymorphism you want from the singly-inherited hierarchies you can
build with class extension. To help you get more polymorphism than you can easily get with single-
inheritance, Java supports a restricted form of multiple inheritance through a construct called the
"interface." This chapter will discuss the motivation and the mechanics of the Java interface.

The Limitations of Single Inheritance

To reap the benefits of polymorphism through class extension, you must build a family of
classes. In Java terminology, both classes and interfaces are "types." When you declare an
interface, as when you declare a class, you establish a new type. In the remainder of this book, "type" will
be used to refer to either classes or interfaces. Here, a "family of classes" is simply a family of types in
which all the types are classes (none are interfaces). Thus, a family of classes is a group of related classes
with a single base class from which all other classes in the family descend. Since every class in Java
descends from Object, all Java classes are members of the
Object family; however, you can still look at individual areas of an inheritance
hierarchy as individual "families of classes." For example, class Cup and all its
subclasses, as shown in Figure 4-1, form the Cup family.
[bv: I believe I covered this already in a previous chapter.]

Figure 4-1. The Cup family

Given a family of classes, polymorphism allows you to treat a subclass object as if it were a superclass
object. For example, imagine you wanted to create a single method that could wash any kind of cup in
your virtual cafe. You could declare a public method named wash() in the base class
of the Cup family:

Here you have all the benefits of polymorphism. The prepareACup() method
can invoke wash() on many different objects, but it doesn't need to use
instanceof. As a consequence, the code is easier to read and change. If later, you
wanted to add class TeaCup to your program and wash TeaCup
objects with prepareACup(), you only need to make TeaCup a
subclass of Cup. You don't need to change the prepareACup()
method itself.

This all works fine, but what if you wanted to wash a greater variety of objects with a single method?
What if you wanted to have a method that can wash any kind of object for which washing makes sense--
any "washable" object? For example, besides washing cups, you might also want to wash a window, wash
your car, or wash a dog. Since these objects don't seem to fit into the same family, you might end up using
instanceof instead of polymorphism. For example, consider these classes:

Here, instead of having one family of classes for washable objects, you have four separate families:
cups, dogs, cars, and windows. Each washable object in each family declares wash(),
but because there is no common base class that declares wash(), you can't use
polymorphism. To create a method that can wash any of these kinds of objects, your method would have to
use instanceof:

This cleanAnObject()method will work, but it doesn't participate in the
benefits of polymorphism. Most significantly, this code is less flexible than if it were able to take
advantage of polymorphism. With the above code, you'd have to add another
instanceof check if you want to add another kind of washable object, say
Bicycle, to your program.

To improve this situation, you might decide to give cups, cars, windows, and dogs a common base
class that declares the wash() method. This would allow you to get the full benefit of
polymorphism in the cleanAnObject() method. Here, the four families--cups,
cars, windows, and dogs--are combined into the WashableObject family:

As this example demonstrates, it is possible to fit cups, windows, cars, and dogs all into the same
family of classes; however, the resulting family, WashableObject, is not very
intuitive and not very flexible.

As an example of this family's inflexibility,
imagine that later you decide you want Dog to descend from
Animal. You would have to make Animal descend from
WashableObject. But what if, as is shown in Figure 4-4, you declared
Cat and Fish as subclasses of Animal too? Is
a Cat washable? Potentially, but you'd best let the Cat take care of
that itself. And how do you wash a Fish? Although each of these washings are
possible to imagine, they may not be a behavior you intend a Cat or
Fish to exhibit. You are making Cats and
Fish endure washing, when all you really want to do is keep the
Dog clean. Given that you want Dogs to both to descend from
Animal and be washable, however, you need to either make every
Animal a WashableObject or every
WashableObject an Animal. Here is the code for the
Animal family:

The problem here is that you are using class extension not to model specialization of objects in
the problem domain, but simply to get at polymorphism. In your problem domain, is it true that a
Cup is-a WashableObject? What exactly is a washable object?
What does one look like? Washable is an adjective, not a noun. It describes a behavior exhibited by
objects, not an object itself. To get the benefits of polymorphism, you insert
WashableObject into the inheritance hierarchy, but it doesn't fit very well.

Multiple Inheritance with Interfaces

Although class extension only allows single inheritance (each class can have at most one direct
superclass), Java offers a special variation of multiple inheritance through the "interface." An interface is
like an abstract class that has only publicabstract methods
and publicstaticfinal fields. An
interface (the Java construct) represents a pure interface (the object-oriented concept); it has no
implementation.

Interfaces in Java allow you to get the benefits of polymorphism without requiring you to build a
singly-inherited family of classes. Although a class can extend only one other class, it can "implement"
multiple interfaces. Interfaces allow you to use families of classes to model what objects are (such as cups
or animals) rather than what you plan to do with them (such as wash them). You can design a family of
classes for cups, another for animals (including dogs), one for vehicles (including cars), one for parts of a
building (including windows). Then each washable class can implement the
Washable interface.
Here is a potential declaration of the interface:

The methods declared in this interface are not explicitly declared public and
abstract, because they are public and
abstract by default. Likewise, the constants
in Washable are
not declared public, static, and final,
because they are so by default.

Class Cup declares that it implements interface
Washable, so it must implement each method contained in that
interface. If
it doesn't, it must declare itself as abstract. (If class Cup
didn't implement the
methods contained in the interfaces and didn't declare itself abstract, it
wouldn't compile.) In this case, it
implements all methods declared in Washable.
Class CoffeeCup, which extends class Cup, can either inherit or
override Cup's implementation of the methods defined in
Washable and Breakable. Figure 4-5 shows an inheritance
hierarchy for this version of class Cup and CoffeeCup.
[bv: Explain the UML diagram for interfaces.]
Note that interfaces do not descend from class Object.

Figure 4-5. An inheritance hierarchy that includes interfaces

Although interfaces (like abstract classes) cannot be instantiated by themselves, you can create a
variable to hold a reference to an interface type:

Thus, you can upcast a CoffeeCup reference not only to a
Cup or an Object reference, but also to a
Washable reference as well. On an interface
reference such as wa above, you can invoke any method declared in the interface, as
wash() was in this example.

The Interface Solution

Given the Washable interface, you could
overcome the difficulties encountered earlier in writing
cleanAnObject().
Here is how you could declare the classes and the interface:

The inheritance hierarchy for these classes is shown in Figure 4-6. Given these definitions for cups,
animals, windows, and cars, you could once again get the benefits of
polymorphism when writing method cleanAnObject():

Interfaces allow you to get the benefits of polymorphism without requiring that you fit everything into
one singly-inherited family of classes. In the examples above, the Washable interface defines a
standard way to do washing, and any class can implement it.
Because of interfaces, you can use class extension to model what objects are.
You can use interface implementation to get polymorphism based purely on what an object
does. Any desired polymorphism that class extension doesn't
produce, you can get with interface implementation.

Implementing Multiple Interfaces

[bv: have one example of this.]

Interfaces Extending Interfaces

Similar to classes, you can build up inheritance hierarchies of interfaces by using the
extends keyword, as in:

In this example, interface Soakable extends interface
Washable. Consequently, Soakable inherits all the members of
Washable. A class that implements Soakable must provide
bodies for all the methods declared in or inherited by Soakable,
wash() and soak(), or be declared abstract. Note that only
interfaces can "extend" other interfaces. Classes can't extend interfaces, they can only implement
interfaces.

Soakable inherits member wash()from its
superinterface.
Similar to "subclass" and "superclass," interfaces in an inheritance hierarchy
can be called "subinterface" and "superinterface." To refer to either classes or interfaces, you can say
"subtype" and "supertype." As with subclass and superclass, you can use "direct" to indicate that a type or
interface is a direct descendant or ancestor of another type or interface, as in "direct superinterface" or
"direct subtype."

To extend the previous example further, here are a few more interfaces:

In this example, Washable, Soakable, and
Scrubable are all superinterfaces of BubbleBathable. (Note
that BubbleBathable extends two direct superinterfaces. Just as classes can
implement multiple interfaces, interfaces can extend multiple interfaces.) Classes that implement
BubbleBathable must therefore provide bodies for methods declared in
Washable, Soakable, Scrubable, and
BubbleBathable, or be declared abstract. Figure 4-7 shows the inheritance
hierarchy for this family of interfaces.

Figure 4-7. Interfaces can extend other interfaces

Using instanceof with Interfaces

Given a reference to an object, you can find out if a particular interface is a superinterface of that
object's class by using instanceof. For example, the
washIfPossible() method, shown below, uses instanceof
to determine whether an object is a subtype of the Washable interface:

Alternatively, you can obtain a list of all the interfaces an object's class implements using the
java.lang.Class object. This will be described in the chapter on Reflections,
Chapter 19. These mechanisms allow you to query an object to find out what methods you can invoke on
it, or "what it can do for you."

Name Conflicts

Multiple inheritance brings with it the potential for name conflicts. If, for example, the
Soakable and Scrubable interfaces both declare a method
named dryOff(), classes that implement both Soakable and
Scrubable would inherit dryOff() twice. If
dryOff() has different signatures in both interfaces, then the class would inherit two
overloaded names, and would have to define implementations for both, or else declare itself as abstract:

If both Soakable and Scrubable declared two constants
with the same name, that in itself would never prevent a class from implementing both interfaces. The
like-named constants can be of different values and even different types. To refer to one of the constants
from with the class, however, you must use the qualified name of the field (the name of the
interface, a dot, and the name of the field):

Interfaces versus Plain-Old Multiple Inheritance

Interfaces Don't Have the Diamond Problem

Interfaces and Composition

Here talk about the "weight" of plain-old multiple inheritance
using the washing machine example. Talk about the advantages
of using interfaces to get polymorphism and composition
to get reuse.

Interface Naming Conventions

The style conventions proposed by the Java Language Specification
encourage you to leave off redundant modifiers in member declarations of interfaces. (Note that this is not
an issue with classes, because classes can't have redundant modifiers.)

The Java Language Specification's recommended naming conventions for interfaces are either a noun
or noun phrase, if you are using the interface to represent an abstract base class, or an adjective, if you are
using the interface to represent a behavior. (Here, both Washable and
Breakable are being used to represent a behavior, so their names are adjectives.
Using an interface to represent an abstract base class will be discussed later in this chapter.) The
capitalization of interface names follows that of classes: the first letter of each word should be upper case,
the rest lower case.

Interface Implementation Strategies

An interface can have several possible implementations, each appropriate for different classes of
objects or different situations. The implementations can vary in the algorithm or data structures used,
yielding, for example, some methods that are faster but use a lot of memory and others that are slower but
use memory more conservatively. Sometimes a method declared in an interface simply has a slightly
different meaning for the various classes that implement the interface. For example, you might wash an
object differently depending upon what the object is. Some ways you could the wash an object are: with
soap, water, and a sponge; with sudsy water and a squeegee; with glass cleaner and a paper towel; or with
a machine. The appropriate way for a class to implement the wash() method of the
Washable interface depends upon that class's unique nature or circumstances.

If you are writing a class that has superinterfaces, you must implement all methods defined in the
superinterfaces, or declare the class abstract. There are three approaches you can take to implement those
methods:

implement them directly,

inherit an implementation, or

forward the call to another class's implementation.

If a class has a unique manner of implementing an interface, it can take the first approach and
implement it directly. For example, if there is a way to wash cups that is unique to cups, class
Cup could declare a wash() method that washes in that unique
way. Subclasses of Cup would then have the option of inheriting Cup's implementation (the second
approach) or overriding it:

Sometimes a single implementation of an interface may make sense for different objects that aren't in
the same family of classes. As an example, imagine you wanted to be able to add properties to some of
your classes, where a property is a value string indexed by a key string. If a particular property's key
string were "color", for example, its value string could be
"blue". You want to be able to add properties, remove properties, and lookup a value
given a key. Because this behavior is something you'd like to be able to apply to any kind of object, an
interface is called for:

You may wish to add properties to both cups and cars, for example, and use the same mechanisms for
managing the data. Instead of repeating the same implementation of
setProperty(), removeProperty(), and
getProperty() in both the Cup and Car
classes, you could create a PropertyManager class that implements the
Propertied interface:

The PropertyManager class represents one way to implement the
Propertied interface. This implementation uses the
Hashtable class from the java.util library. (The name
java.util.Hashtable is Hashtable's fully qualified
name. The details of fully qualified names are described in the next chapter.) Note that this class
uses composition. Class PropertyManager has-a Hashtable.

Cup and Car objects could each contain a
PropertyManager object and then forward calls to their
PropertyManager. (This is the third approach from the list above.):

Any other classes that you later decide could use a Hashtable for implementing
the Propertied interface could contain a PropertyManager
object and forward calls to it. If you later encounter classes for which it doesn't make sense to use a
Hashtable, you could write another class, perhaps
LinkedListProperyManager, that implements
Propertied in a different way. Those classes for which a
Hashtable doesn't make sense could contain a
LinkedListProperyManager object and forward calls to it.

Using Interfaces as Abstract Base Classes

As mentioned before, the Java Language Specification suggests two conventions for naming
interfaces. If the interface represents a behavior, its name should be an adjective. The interfaces given so
far as examples in this chapter, Washable, Breakable, and
Propertied fall into this category. They represent pure behavior, and their names
are adjectives. The other suggested naming convention is for interfaces that serve as abstract base classes.
In this case, interfaces should be given names that are nouns or noun phrases, just like classes.

As described in the previous chapter, you can declare classes abstract. If you have a class that is
conceptual only--not one that represents actual objects, but one that represents a category of types--you
should declare that class abstract. An abstract class cannot be instantiated. Instead of serving as a
blueprint for instantiating objects, an abstract class serves as a base class in a family of types.

For example, you could decide that in your virtual cafe, you have coffee cups and tea cups. In your
inheritance hierarchy, you could define an abstract class Cup that serves as a base class
for both CoffeeCup and TeaCup. The abstract
Cup class could define abstract methods that both CoffeeCup and
TeaCup must implement:

Given this inheritance hierarchy, shown graphically in Figure 4-8, you could not instantiate a
Cup object, but you could use a Cup reference to send messages to
a CoffeeCup or TeaCup object. Given a Cup
reference that refers to a CoffeeCup or TeaCup, you could
invoke add(), releaseOneSip(), or
spillEntireContents() on it. The implementation of those methods that
actually gets invoked at run-time will depend upon the actual class of the object referred to by the
Cup reference.

Figure 4-8. Cup as an abstract base class

Since this class Cup contains only public abstract methods, it could alternatively
be declared as an interface:

Here you are using an interface to represent an abstract base class. As suggested by the Java Language
Specification, the name of the class, Cup, is a noun. The inheritance hierarchy for this
is shown in Figure 4-9.

Figure 4-9. Cup as an interface

In general, if you have an abstract base class that declares only public abstract methods and public
static final fields, you may as well make it an interface. Because an abstract class is restricted to single
inheritance, but an interface can be multiply inherited, an interface is more flexible than an abstract class.
If you want to have any default implementation of methods, or non-public members in the base class,
however, it must be an abstract class.