Chapter 8. Interfaces

Interfaces

Interfaces are an important concept in Java. In this chapter we’ll explain how you use interfaces and how they work. We’ll start by describing the problem that they solve.

What Problem Does an Interface Solve?

We’ve seen in previous chapters how classes can be related in a hierarchy, with the common behavior higher up the tree. An example is given in Figure 8-1.

Where should the refuel() method go?

Figure 8-1. Where should the refuel() method go?

The figure shows some classes relating to means of transport. Each box is a class, labeled with the class name, and with an example method that belongs in that class. The parent class is called “Transport” and has a method called “buy()”. Whatever kind of vehicle you have, you have to buy it before it becomes yours. Putting the method in the parent class means that all subclasses inherit it.

Transport has three child classes. The class called “Car” has a method called “drive(),” and this is inherited by its two subclasses, Convertible and Saloon. Whatever kind of car it is, the way you move it is to drive(). It belongs in Car, not Transport, because you don’t drive a bicycle or an airplane.

Now let’s imagine we want to keep refuelling information in this class hierarchy. We want to add a method called “refuel( )” that fills the fuel tank of each vehicle. The class that keeps track of our supply depot will call the refuel method on vehicle objects. Where is the right place to add refuel() in the tree of classes?

We cannot add a refuel() method in the transport class, because Bicycle would inherit it, and bicycles are not refuelled. We can add the method individually to Airplane and Car and any other unrelated Classes, like Generator, that represent something that can be refuelled.

That’s good, but it causes problems for our supply depot class. The supply depot class will call an object’s refuel() method. What should be the type of the things we pass to it for refuelling? We cannot pass a Transport, because not all transport objects have a refuel method(), and some non-Transport things (like Generator) need refuelling

We could overload service() with one version for each type that has a refuel method. But that’s not very convenient. Even worse, if we come along with some new thing that is capable of being refuelled, like a JetSki, we now have to modify the SupplyDepot class to add a service (JetSki thingToSupply) method. Well-designed systems don’t cause changes to ripple across classes this way.

We are looking for a way to say “I represent any type that has a refuel() method” (see Figure 8-2). Then we just make the argument to service() be that type. Some OOP languages allow classes to have more than one parent, a feature known as “multiple inheritance.” Multiple inheritance would solve this problem by having a class called “CapableOfBeingRefuelled” with a single method called “refuel().” Everything that can be refuelled will be where it is now in the class hierarchy, but it will also have CapableOfBeingRefuelled as a second parent.

What type should thingToService be to represent everything that has a refuel( ) method?

Figure 8-2. What type should thingToService be to represent everything that has a refuel( ) method?

When a language has multiple inheritance, it often proves to be a controversial feature because it seems to need a great many confusing and unintuitive language rules. Java does not have a multiple inheritance feature, but it has something that fills a similar role in a simpler way. Step forward, interfaces!

Interfaces are in the Java language to allow a class to say it has some particular behavior and to act as a placeholder for real classes in any place where that behavior is expected.

We already saw something similar with inheritance, but you can inherit only from one class. A class can implement any number of interfaces. Interfaces say, “I offer this kind of behavior, and you can later use any object from a class that implements me in any place you are using me.” Interfaces provide the functionality of multiple inheritance, without the difficulties.

Remember some of the sample Java classes, like java.lang.String and java.lang.Integer we have presented, saying “here is the API” and showing a list of the method names? The “I” in API even stands for “Interface” (Application Programmer Interface). That is exactly what a Java interface is: a class-like thing that just has a list of method names, not the method bodies. For this reason, some people say that “Java has multiple inheritance of interface, but not multiple inheritance of implementation.”

An interface is a skeleton of a class showing the methods the class will have when someone implements it. An interface looks like this:

public interface CapableOfBeingRefuelled {
     public int refuel(); 
} 

An interface looks a bit like a class (actually, more like an abstract class), is counted as a reference type, and can generally be used in most of the same places as a class. It doesn’t have any behavior, though—it’s just a description of promised behavior. The declarations in an interface—the fields and methods—are always public, even if you don’t label them. The fields in an interface are final, even if you don’t label them so. The methods in an interface are abstract, even if you don’t label them so.

Any class that has a refuel method should say that it implements the CapableOfBeingRefuelled interface, like this:

public class Airplane implements CapableOfBeingRefuelled { 
     public int refuel() {
          purgeWingTanks(); 
          leftTank += this.capacity; 
     } 
     ... // more methods, omitted 
} 

Now here comes the clever part. The SupplyDepot’s service method will take an argument that is type CapableOfBeingRefuelled! Class Airplane, Generator, JetSki, Car and so on all have that type by virtue of implementing that interface. Therefore, they can all be passed to the service method. SupplyDepot will look like this.

public class SupplyDepot {
     public void service(CapableOfBeingRefuelled thingToService) {
          thing.refuel(); 
     } 
     ... // more methods, omitted 
} 

And when we come along with something additional that needs to be refuelled, like a snowmobile, no further change is needed in the SupplyDepot class. The snowmobile will be declared as follows, and it is therefore already compatible with the argument to SupplyDepot’s service() method:

public class Snowmobile implements CapableOfBeingRefuelled { 
     public int refuel() {
               ... 
     } 

     ... // more methods, omitted 
} 

The fundamental reason for interfaces is to decouple or separate some behavior that you know some classes have from the classes that use that behavior. In summary:

  • Use the interface type as a parameter for a method. Inside the method you can invoke any of the methods promised by the interface parameter. When you actually call the method, you will have to provide an object that implements the interface and thus has all the methods promised by the interface.

  • Interfaces let you compile your code now. But you need to provide an object with actual code for the thing to work at runtime.

  • The interface specifies the exact signatures of the methods that must be provided by the implementing classes.

With interfaces, you can write code that makes calls on classes that haven’t even been written yet. A class can come along later and be used in the places where you have used the interface— as long as it says it implements the interface.

Comparable

Interfaces are used frequently in the Java runtime library. Here is a complete example of interface Comparable in the java.lang package:

public interface Comparable { 
     public int compareTo(Object o); 
} 
/** 
 * Compares this object with the specified Object o for order. 
 * 
 * Returns a negative integer, zero, or a positive integer 
 * if this object is less than, equal to, or greater than the 
 * specified object.<p> 
 */ 

An interface name often includes the suffix “-able.” That happens naturally because interfaces describe some capability. The package java.lang has four interfaces, three of which are “-able”:

  • java.lang.Cloneable —. this interface is an example of the “marker” design pattern. It has no members, but signals to the compiler that some behavior is permitted. There is a full description of Cloneable later in the chapter.

  • java.lang.Comparable —. this interface promises a method that allows two objects of the same class to be placed in order with respect to one another, i.e., they can be compared. We’ll show a complete example of using the Comparable interface.

  • java.lang.Runnable —. this interface promises a run() method which allows an object to execute as a separate thread of control. A couple of later chapters deal with threads of control.

A class that fulfills the interface will use the keyword “implements” like this:

public class Double implements Comparable { ... 

If you want to peek ahead, this class is the standard java.lang.Double class featured at the end of this chapter. Double is an object wrapper for double precision floating-point numbers, meaning that it provides a thin object layer over the primitive type. It thus allows you to send along a double primitive type argument to all the classes that require an object as an argument.

When we see the line of code above, we know at once that Double has a method with the compareTo signature because that’s what the Comparable interface promises. Objects of class Double can be used anywhere you have used the Comparable interface.

A class can extend only one superclass, but it can implement any number of interfaces. Two interfaces can make the same demand for a method of a given name in a class without problems (one of the situations that causes tic douloureux among the multiple inheritance crowd). Different classes can implement the same interface each in their own special way.

Here’s some more code from the Double class. The class Double implements the Comparable interface by providing a body for the compareTo method. This is the actual source code from the runtime library. The runtime library source code is distributed as part of the JDK, and it is instructive to read it.

public class Double implements Comparable { ... 

     public int compareTo(Object o) { 
          anotherDouble = (Double) o; 
          double anotherVal = anotherDouble.value; 
          double thisVal = value; 

          if (thisVal < anotherVal) 
               return -1; // Neither val is NaN, thisVal is smaller 

          if (thisVal > anotherVal) 
               return 1; // Neither val is NaN, thisVal is larger 

          // tricky code dealing with NaN’s, omitted 
          return 0; 
     } 

// other methods in the class omitted ... 
} 

Look at the source in $JAVAHOME/src/java/lang/Double.java if you are curious about the NaN trickiness which I have left out of this example.

The code here says that if I see anything that takes a Comparable as an argument, I can actually call it with a Double object. The reason is that Double has all the behavior promised by Comparable. Here’s an example showing it being used as an argument type:

java.lang.Runnable —

Getting more detailed, I can write a data structure that sorts an array. Instead of making it an array of some fixed type like, say, Integer, I can make it process an array of Comparables. Then anything that implements the interface can use my sort class! Here’s how some of the code might look:

// first, a reminder of the interface 
public interface Comparable {
     public int compareTo(Object o); 
} 

// next, my sortingClass to sort anything that can be 
// compared, making use of the Comparable interface 

public class sortingClass {
     // holds the data 
     static java.lang.Comparable [] d; 

     // a constructor, to fill up the d array 
     sortingClass(java.lang.Comparable data[]) { d=data; } 

     int findLargest() {
          java.lang.Comparable largestSoFar = d[0]; 
          int where = 0; 
          for (int i=1; i<d.length; i++) {
               if (largestSoFar.compareTo(d[i]) == -1) {
                    largestSoFar = d[i]; // new element is bigger 
                    where = i;           // so record where it is 
               } 
          } 
          return where; 
     } 

     ... // more methods, omitted 

In the body of the findLargest() method, we look at successive elements of the array called d, and compare them using the compareTo method. This is a neat trick. We have promised only that method so far and not actually supplied a body for it. It’s enough to allow compilation to take place. We can’t actually run the code until we supply a class that implements the interface.

To keep the example small, I haven’t filled up the page with code showing the rest of a sort algorithm. You’ll have to believe me when I say that by finding the largest thing left in a pile of objects, you can sort the objects. That is how the bubblesort algorithm works, though everyone knows that the only virtue of bubblesort is that it is easy to understand. It is too slow to use when you actually want to sort, instead of teach.

Here’s how some code to fulfill the interface might hook up with the sortingClass. Double implements Comparable, so we can pass a Double array to the sortingClass constructor that expects a Comparable array:

public static void main(String[] args) {
     Double dubs [] = { new Double(4.0), new Double(10), 
                         new Double(-9.2), new Double(0.6), 
                         new Double(1),    new Double(99), 
                         new Double(6.00) 
                    }; 

     sortingClass s = new sortingClass( dubs ); 
     int i = s.findLargest(); 
     String val = s.d[i].toString(); 
     System.out.println("Largest is "+ val + " at element "+i); 
} 

Sure enough, when we run that code, it will print out the following message:

% java Try 
Largest is 99.0 at element 5 

This demonstrates that the correct substitution of Double’s version of compareTo() was made in the sortingClass. Better yet, the very same sortingClass works if we instantiate it with Integer objects.

Integer ints [] = { new Integer(4),new Integer(10), 
                    new Integer(9), new Integer(6), 
                    new Integer(1), new Integer(99), 
                    new Integer(600) }; 

sortingClass s = new sortingClass( ints ); 
int i = s.findLargest(); 
String val = s.d[i].toString(); 
System.out.println("Largest is "+ val + " at element "+i); 

This results in the following:

% java Try 
Largest is 600 at element 6 

Don’t be misled into thinking that interfaces are a replacement for C++ templates (i.e., writing a single method body and then having some compiler magic so it can operate on several types that are not related to each other). Templates or generic types form a different feature that is planned for JDK 1.5.

The point is that the interface allows the class that uses it to be freed from any one specific datatype as an argument. The interface lets you use sortingClass with any type that implements the Comparable interface, even a type that hadn’t been thought of when sortingClass was written. If the class implements Comparable, you can use the sortingClass on it.

Think of interfaces as being like a library of stub bodies against which you can compile, but you have to supply a real library at runtime before you actually make the calls.

Interfaces vs. Abstract Classes

While an interface is used to specify the form that something must have, it does not actually provide the implementation for it. In this sense, an interface is a little like an abstract class that must be extended in exactly the manner that its abstract methods specify.

An interface differs from an abstract class in the following ways:

  • An abstract class is an incomplete class that requires further specialization. An interface is just a specification or prescription for behavior.

  • An interface doesn’t have any overtones of specialization that are present with inheritance. It merely says, “We need something that does ‘foo’ and here are the ways that users should be able to call it.”

  • A class can implement several interfaces at once, whereas a class can extend only one parent class.

  • Interfaces can be used to support callbacks (inheritance doesn’t help with this). This is a significant coding idiom. It essentially provides a pointer to a function, but in a type-safe way. The next section explains callbacks.

Here’s the bottom line: You’ll probably use interfaces more often than abstract classes. Use an abstract class when you want to initiate a hierarchy of more specialized classes and provide a partial implementation with fine control over what is private, public, protected, etc. Use an interface when you need multiple inheritance of design to say, “this class has behavior (methods) A, B, and C.”

An interface can be extended, but only by another interface. It is legal for a class to implement an interface but only have some of the methods promised in the interface. You must then make it an abstract class that must be further extended (inherited) before it can be instantiated.

Granting Permission Through an Interface—Cloneable

When we looked at the Object class in Chapter 3, we saw that it has this method:

protected native Object clone() throws CloneNotSupportedException; 

Java supports the notion of cloning, meaning to get a complete bit-for-bit duplicate of an object.

Not every class should support the ability to clone. If I have a class that represents a set of objects that are unique in the real world, such as the ships in a company fleet, the operation of cloning doesn’t make sense, as it doesn’t represent anything in the real world. However, methods (including the clone() method) in the class java.lang.Object are inherited by all classes.

So Java places a further requirement on classes that want to be cloneable: they must implement the cloneable interface to indicate that cloning is valid for them. The cloneable interface is this:

public interface Cloneable { } // completely empty 

The empty interface as a marker is not the most common use of interfaces, but you do see it in the system libraries. To have a class that can be cloned, you must state that the class implements the Cloneable interface.

public class ICanBeCopied implements Cloneable { ... 

Why wasn’t the method clone() of Object made part of the Cloneable interface? That seems like the obvious place to put it, instead of in Object. The reason is that we have two conflicting aims. We want to provide a default implementation of clone so that any cloneable class can automatically inherit it, and that implementation cannot be put in an interface. We also want individual classes to take an extra step to permit cloning on their object.

The end result is that we require, at minimum, an extra step of having cloneable classes implement the Cloneable interface. The class Object does not implement Cloneable itself, otherwise all its descendants (which is every object in existence) would too. We provide a default implementation by putting the method clone, with a body, into the root superclass Object. That implementation could not be placed in an interface, since interfaces only hold method signatures and final data.

Note that clone() returns an Object. The object returned by clone() is usually cast immediately to the correct type, as in this example:

Vector v = new Vector(); 
Vector v2; 

v2 = (Vector) v.clone(); 

Since Arrays are considered to implement Cloneable, they can be copied by System.arrayCopy or by clone().

What Protected Really Means

Object.clone() is protected because subclasses might want to restrict access to cloning, and if Object.clone() were declared public, subclasses could never make it more restrictive. Subclasses can make access to their overriding methods less restrictive, but never more restrictive.

This means that a method can clone its own objects, but a method cannot clone objects of another class unless or until you open up access like this:

class b implements Cloneable {
     public Object clone() 
             throws CloneNotSupportedException { 
            return super.clone(); 
     } 

int b = 22; 
} 

i.e., override clone() to make it public, and call the superclass clone().

Cloning, perhaps surprisingly, does not invoke any constructor.

This is a good place to clarify what the “protected” access modifier does. The JLS (Java Language Specification, which is online at java.sun.com/docs/books/jls/second_edition/html/jTOC.doc.html) says in section 6.6.2:

Let C be the class in which a protected member m is declared. Access is permitted only within the body of a subclass S of C. In addition, if id denotes an instance field or instance method, then if the access is by a qualified name Q.id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.

Loosely rephrasing that in English, protected access means that other classes in the same package can access the member, and subclasses in other packages can access the member. To understand exactly what that means, consider these two classes, which we will put in different packages to be sure we are testing the subclasses part of the rule:

package somePackage; 
class Parent {
     protected int x; 
} 

and

class Child extends Parent { ..... } 

The class Child can only access “x” on objects that are of type Child or that are a subtype of Child. If an equal() method is added to Child, then the following two uses of “x” are both legal:

boolean equal(Child other) {
     return x == other.x; 
} 

They are legal because the left-most “x” is implicitly “this.x”, and both “this” and “other” are of type Child. However, adding this method to Child will cause a compilation error:

int getIt(Parent p) {
     return p.x; /// BAD! BAD! BAD! 
} 

The problem is that the class Child can only access “x” on objects that are of type Child or that are a subtype of Child. The type p is not Child or a subtype, it is the Parent type. You don’t have access to protected members of your superclass, only to protected members of your own class that you inherited because they are accessible members of your superclass.

“static” protected variables and methods are accessible from any child class since there is no “object” through which to access them. “ super.protectedMethod(...) ” is always legal.

People learning about this subtlety often wonder if they have wandered into a C++ book by mistake. Don’t worry! There are hardly any other pitfalls like that in Java. Well, at least compared with some other languages, I mean. For historians and language theologians, this meaning of protected was a change made to Java between JDK 1.0 Beta 1 and Beta 2 in December 1995.

Interfaces in the Java Runtimes

Interfaces are used in many places in the Java runtimes. The utility class java.util.Vector implements three interfaces, as shown below:

public class Vector extends AbstractList 
     implements List, Cloneable, java.io.Serializable { ... 

The Cloneable class is described above. By implementing a List, the class is announcing that it can be used wherever a List is used. It can also do all the things a List can do, meaning it can have elements added or removed, can be checked for being empty, can tell you its size, and so on.

By implementing Serializable, the class Vector is saying that it and all of its subtypes have the ability to be serialized. Being serialized is the conversion into a stream of bytes that can be written out to disk and later reconstituted into an object. This is the same permission-granting use of an interface that we saw with Cloneable.

Call Backs

The examples of interfaces thus far have solved compile time issues. There is an additional way that an interface can be used to obtain more dynamic behavior, which forms the basis of GUI programming in Java. We have already seen this; the explanation here has a different nuance.

Once we have defined an interface, we can use it as the type of some parameter to a method. Inside the method we can use that parameter to invoke the operations that the interface promises. Whenever we make a call to that method, we can pass it a class that implements the interface, and it will call the appropriate method of that class. The following four steps should make this a little clearer.

  1. Define an interface that promises a method called run like this:

    interface Runnable {
         public void run(); 
    } 
  2. Now sprinkle calls to “run” throughout our code, even though we don’t yet have anything that fulfills the interface.

    void vitalSystemThing(Runnable r) {
         r.run(); 
    } 

    This code can be compiled, and may even be part of the Java runtime library.

  3. At a later time and in another file, provide a class (or several classes) that implements the following interface:

    class myCode implements Runnable {
         public void run() {
              System.out.println("You called myCode.run()"); 
         } 
         // other code ... 
    } 
  4. Pass myCode object to the vitalSystemThing:

    myCode myobj = new myCode() 
    vitalSystemThing( myobj ); 

vitalSystemThing can even save a reference to myobj and later call its methods as needed. This is how event handling works in the GUI.

Whenever the vitalSystemThing is invoked, it results in myCode.run() being called back. This is therefore known as a callback. It’s a drawn-out way of doing what you do with a function pointer in C or C++, and this has led some people to call for the addition of function pointers to Java. That won’t happen since Java callbacks are type-safe, but function pointers might not be.

The main reason for writing your code this way is that it decouples the calling routine from the called-back routine. You could have several different classes that implement the Runnable interface. Callbacks allow any of them to be sent to the vitalSystemThing and hence to be called back. The correct class is called back, based on the type at runtime.

There actually is a built-in Java interface, called Runnable, that is used in this way for threads. It is described in Chapter 10. The use of an interface allows the runtime system to schedule and control threads that you implement and compile later. Here is another example of an interface used as a callback:

interface runnable {
    public void run(); 
} 

public class VeryDynamic {
   public static void main(String args[]) {
        runnable r; 
        try {
           Class unknown = Class.forName(args[0]); 
           r = (runnable) unknown.newInstance(); 
           r.run(); 
        } catch (Exception e){ e.printStackTrace();} 
   } 
} 

class Coffee implements runnable {
   public void run() { System.out.println("Coffee.run called"); } 
} 

class Tea implements runnable {
   public void run() { System.out.println("Tea.run called"); } 
} 

The try and catch statements are required to accommodate the exceptions that the enclosed statements might cause. If you compile this program, you can run it like this:

java VeryDynamic Tea 

Try executing it with an argument of “Coffee” and an argument of “Bogus.” The three lines in bold simply get the runtime type information for the class whose name you give as an argument. They then create an instance of that class that is cast to runnable, and call the run() method of that class.

The example demonstrates how a callback can work for an object of a class that isn’t even known until runtime. It doesn’t get any more dynamic than that! The technique is used extensively in the Java GUI library to tell your code about events happening on screen.

Using Inter faces for Named Constants

Using Inter faces for Named Constants

There’s another unorthodox way to use an interface that forms a useful programming idiom. If you have a group of related constants, perhaps of the kind you would put in an enumerated type (if the language has enumerated types), you might gather them in a class like this:

public class FightingWeight {
   public static final int        flyweight = 100; 
   public static final int     bantamweight = 113; 
   public static final int    featherweight = 118; 
   public static final int      lightweight = 127; 
   public static final int     welterweight = 136; 
   public static final int     middleweight = 148; 
   public static final int lightheavyweight = 161; 
   public static final int      heavyweight = 176; 
} 

Then, to use the constants in another class, you would have to do something like this:

static int title = FightingWeight.heavyweight; 

Let’s say you make FightingWeight an interface, like this:

public interface FightingWeight {
   public static final int        FLYWEIGHT = 100; 
   public static final int     BANTAMWEIGHT = 113; 
   public static final int    FEATHERWEIGHT = 118; 
   public static final int      LIGHTWEIGHT = 127; 
   public static final int     WELTERWEIGHT = 136; 
   public static final int     MIDDLEWEIGHT = 148; 
   public static final int LIGHTHEAVYWEIGHT = 161; 
   public static final int      HEAVYWEIGHT = 176; 
} 

You can then reference the names directly. Wow!

class gooseberry implements FightingWeight {
   ... 
     int title = HEAVYWEIGHT; 

Final variables are usually written in all capitals (a holdover from C). The interface javax.swing.WindowConstants uses this technique. Name inheritance works for classes, too, but it’s considered poor style to extend a class just for better name visibility.

The Class Double

Here is the declaration of class java.lang.Double:

public final class java.lang.Double extends java.lang.Number 
                                   implements java.lang.Comparable {
     // constructors 
     public java.lang.Double(double); 
     public java.lang.Double(java.lang.String) 
                         throws java.lang.NumberFormatException; 
     public static final double POSITIVE_INFINITY = 1.0 / 0.0; 
     public static final double NEGATIVE_INFINITY = -1.0 / 0.0; 
     public static final double NaN = 0.0d / 0.0; 
     public static final double MAX_VALUE = 1.79769313486231570e+308; 
     public static final double MIN_VALUE = longBitsToDouble(1L); 
     public static final java.lang.Class TYPE= 
                                   Class.getPrimitiveClass("double"); 

     public byte byteValue(); 
     public short shortValue(); 
     public int intValue(); 
     public long longValue(); 
     public float floatValue(); 
     public double doubleValue(); 

     public int compareTo(java.lang.Double); 
     public int compareTo(java.lang.Object); 
     public boolean isInfinite(); 
     public static boolean isInfinite(double); 
     public boolean isNaN(); 
     public static boolean isNaN(double); 
     public boolean equals(java.lang.Object); 
     public int hashCode(); 
     public static native long doubleToLongBits(double); 
     public static native double longBitsToDouble(long); 

     public static double parseDouble(java.lang.String) throws 
                                   java.lang.NumberFormatException; 
     public java.lang.String toString(); 
     public static java.lang.String toString(double); 
     public static java.lang.Double valueOf(java.lang.String) throws 
                                   java.lang.NumberFormatException; 
} 

Exercises

  1. Describe, without excessive handwaving, two common uses for interfaces.

  2. Use the sorting class shown in this chapter to find the “largest” of a set of Strings you provide. The class java.lang.String implements the Comparable interface.

  3. Take any class that you have written and make it cloneable by making it implement the Cloneable interface. The Cloneable source code is at $JAVA-HOME/src/java/lang/Cloneable.java.

  4. Override Object.clone() to do a shallow copy for your class, and also keep count of the number of objects of your class that have been created. Don’t forget to count those created via a constructor, too.

  5. Write some code to clone an object of your class. Change your version of clone() to do a deep copy for your class. Run the clone program again, and make it print out enough details that you can tell the difference between a shallow clone and a deep clone.

Some Light Relief—The Odyssey of Naming Hal

To close out the chapter, let’s peek at another example of naming and the confusion that can arise. There’s a pervasive industry legend that the antihero computer HAL in the film 2001: A Space Odyssey was so-named to indicate that he was one step ahead of IBM. Alphabetically, “H,” “A,” and “L” precede “I,” “B,” and “M” by one letter.

Similarly, people say that Windows NT (WNT) is one step away from VMS. Dave Cutler designed VMS when he was at Digital and then joined Microsoft to become the chief architect of Windows NT. I believe that the name was chosen with this in mind. It’s a moot point, now that the product has been renamed Windows 2000, to make it look like a continuation of the Windows line. In a sense it is now, since the Windows XP release drops the Windows 3.1, 95, 98, ME line of products, and tries to migrate all consumers to the NT source base under the XP name.

Arthur C. Clarke, the author of 2001: A Space Odyssey, emphatically denies the HAL legend in his book Lost Worlds of 2001, claiming that HAL is an acronym for “Heuristically-programmed Algorithmic Computer.” Clarke even wrote to the computer magazine Byte to place his denial on record. Methinks he doth protest too much.

Certainly, the claims of an involved party are one piece of evidence, but there is no particular reason why they should be accepted uncritically as complete truth. Consider them rather in the context of all pieces of evidence, as happens in courts of law every day. For one thing, “Heuristically-programmed Algorithmic Computer” is a contrived name that does not properly form the desired acronym. For another, all the working drafts of the 2001 story had HAL named “Athena,” and it would have remained so had not Clarke deliberately rechristened it. The odds of him accidentally latching onto the one name that mimics one of the world’s largest computer companies are a few thousand to one.

Why would Clarke deny it if it were true? IBM logos appear in several places in the movie, and the filmmakers clearly cut a deal with IBM for product placement. It may be that Clarke decided to assert some artistic independence by deciding on a name change as a subtle dig at IBM: HAL is a homicidal maniac who goes berserk. Perhaps he was just suggesting that his creation was one step ahead of IBM. Later, when the story got out, Clarke realized he would look foolish, or at the very least ungracious, by lampooning them. So he tried to bluff his way out.

An interesting concern is why the name was changed at all. If Clarke provided an explanation of that along with his denials, the denials would have more credibility.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.134.99.32