[Chapter 3] 3.6 Subclasses and Inheritance

#

| Chapter 3 Classes and Objects in Java |

## 3.6 Subclasses and Inheritance

The `Circle` class we've defined is good for abstract mathematical manipulation. For some applications this is exactly what we need. For other applications, we want to be able to manipulate circles and draw them on the screen. This means we need a new class, `GraphicCircle`, that has all the functionality of `Circle`, but also has the ability to be drawn.

We want to implement `GraphicCircle` so that it can make use of the code we've already written for `Circle`. One way to do that is the following:

    public class GraphicCircle {
        // Here is the mathematical circle.
        public Circle c;
        // Here are the old methods.
        public double area() { return c.area(); }
        public double circumference() { return c.circumference(); }
        // The new graphic variables and methods go here.
        public Color outline, fill;
        public void draw(DrawWindow dw) { /* code omitted */ }
    }

This approach would work, but it is not particularly elegant. The problem is that we have to write stubs for methods like `area()` and `circumference()` that have nothing to do with drawing circles. It would be nice if we didn't have to do this.

### Extending a Class

In fact, we don't have to do it this way. Java allows us to define `GraphicCircle` as an extension, or subclass of `Circle`. Example 3.10 shows how. Note that this example assumes we have two other classes of objects defined: `Color`, which represents a color, and `DrawWindow`, a class that has the window into which drawing is done and that defines the primitive methods to do the drawing.

#### Example 3.10: Subclassing a Class

    public class GraphicCircle extends Circle {
        // We automatically inherit the variables and methods of
        // Circle, so we only have to put the new stuff here.
        // We've omitted the GraphicCircle constructor, for now.
        Color outline, fill;
        public void draw(DrawWindow dw) {
            dw.drawCircle(x, y, r, outline, fill);
        }
    }

The `extends` keyword tells Java that `GraphicCircle` is a subclass of `Circle`, and that it inherits the fields and methods of that class. [7] The definition of the `draw()` method shows variable inheritance--this method uses the `Circle` variables `x`, `y`, and `r` as if they were defined right in `GraphicCircle` itself.

> [7] Except for `private` fields and methods. We'll discuss `private` members of a class later. C++ programmers should note that `extends` is the Java equivalent of the `:` operator in C++--both indicate the superclass of a class.

`GraphicCircle` also inherits the methods of `Circle`. Thus, if we have a `GraphicCircle` object referred to by variable `gc`, we can say:

    double area = gc.area();

This works just as if the `area()` method were defined in `GraphicCircle` itself.

Another feature of subclassing is that every `GraphicCircle` object is also a perfectly legal `Circle` object. Thus, if `gc` refers to a `GraphicCircle` object, we can assign it to a `Circle` variable, and we can forget all about its extra graphic capabilities: `Circle c = gc;`.

### Final Classes

When a class is declared with the `final` modifier, it means that it cannot be extended or subclassed. `java.lang.System` is an example of a `final` class. Declaring a class `final` prevents unwanted extensions to the class. But it also allows the compiler to make some optimizations when invoking the methods of a class. We'll explore this in more detail when we talk about method overriding later in this chapter.

### Superclasses, Object, and the Class Hierarchy

In our example, `GraphicCircle` is a subclass of `Circle`. We can also say that `Circle` is the superclass of `GraphicCircle`. The superclass of a class is specified in its `extends` clause:

    public class GraphicCircle extends Circle { ... }

Every class you define has a superclass. If you do not specify the superclass with an `extends` clause, the superclass is the class `Object`. `Object` is a special class for a couple of reasons:

- It is the only class that does not have a superclass.

- The methods defined by `Object` can be called by any Java object.

Because every class has a superclass, classes in Java form a class hierarchy, which can be represented as a tree with `Object` at its root. Figure 3.1 shows a class hierarchy diagram which includes our `Circle` and `GraphicCircle` classes, as well as some of the standard classes from the Java API.

#### Figure 3.1: A class hierarchy diagram

The complete class hierarchy for the Java API is diagrammed in the figures of Part V, API Quick Reference.

### Subclass Constructors

In Example 3.10 we left out the constructor method for our new `GraphicCircle` class. Let's implement that now. Here's one way:

    public GraphicCircle(double x, double y, double r,
                                    Color outline, Color fill)
    {
        this.x = x;
        this.y = y;
        this.r = r;
        this.outline = outline;
        this.fill = fill;
    }

This constructor relies on the fact that `GraphicCircle` inherits all the variables of `Circle` and simply initializes those variables itself. But this duplicates the code of the `Circle` constructor, and if `Circle` did more elaborate initialization, it could become quite wasteful. Furthermore, if the `Circle` class had internal `private` fields (discussed later), we wouldn't be able to initialize them like this. What we need is a way of calling a `Circle` constructor from within our `GraphicCircle` constructor. Example 3.11 shows how we can do this.

#### Example 3.11: Invoking a Superclass's Constructor

    public GraphicCircle(double x, double y, double r,
                                    Color outline, Color fill)
    {
        super(x, y, r);
        this.outline = outline;
        this.fill = fill;
    }

`super` is a reserved word in Java. One of its uses is that shown in the example--to invoke the constructor method of a superclass. Its use is analogous to the use of the `this` keyword to invoke one constructor method of a class from within another. Using `super` to invoke a constructor is subject to the same restrictions as using `this` to invoke a constructor:

- `super` may only be used in this way within a constructor method.

- The call to the superclass constructor must appear as the first statement within the constructor method. It must appear even before variable declarations.

### Constructor Chaining

When you define a class, Java guarantees that the class's constructor method is called whenever an instance of that class is created. It also guarantees that the constructor is called when an instance of any subclass is created. In order to guarantee this second point, Java must ensure that every constructor method calls its superclass constructor method. If the first statement in a constructor is not an explicit call to a constructor of the superclass with the `super` keyword, then Java implicitly inserts the call `super()`--that is, it calls the superclass constructor with no arguments. If the superclass does not have a constructor that takes no arguments, this causes a compilation error.

There is one exception to the rule that Java invokes `super()` implicitly if you do not do so explicitly. If the first line of a constructor, `C1`, uses the `this()` syntax to invoke another constructor, `C2`, of the class, Java relies on `C2` to invoke the superclass constructor, and does not insert a call to `super()` into `C1`. Of course, if `C2` itself uses `this()` to invoke a third constructor, `C2` does not call `super()` either, but somewhere along the chain, a constructor either explicitly or implicitly invokes the superclass constructor, which is what is required.

Consider what happens when we create a new instance of the `GraphicCircle` class. First, the `GraphicCircle` constructor shown in Example 3.11 is invoked. This constructor explicitly invokes a `Circle` constructor and that `Circle` constructor implicitly calls `super()` to invoke the constructor of its superclass, `Object`. The body of the `Object` constructor runs first, followed by the body of the `Circle` constructor, and finally followed by the body of the `GraphicCircle` constructor.

What this all means is that constructor calls are "chained"--any time an object is created, a sequence of constructor methods are invoked, from subclass to superclass on up to `Object` at the root of the class hierarchy. Because a superclass constructor is always invoked as the first statement of its subclass constructor, the body of the `Object` constructor always runs first, followed by the body of its subclass, and on down the class hierarchy to the class that is being instantiated.

### The Default Constructor

There is one missing piece in the description of constructor chaining above. If a constructor does not invoke a superclass constructor, Java does so implicitly. But what if a class is declared without any constructor at all? In this case, Java implicitly adds a constructor to the class. This default constructor does nothing but invoke the superclass constructor.

For example, if we did not declare a constructor for the `GraphicCircle` class, Java would have implicitly inserted this constructor:

    public GraphicCircle() { super(); }

Note that if the superclass, `Circle()`, did not declare a no-argument constructor, then this automatically inserted default constructor would cause a compilation error. If a class does not define a no-argument constructor, then all of its subclasses must define constructors that explicitly invoke the superclass constructor with the necessary arguments.

It can be confusing when Java implicitly calls a constructor or inserts a constructor definition into a class--something is happening that does not appear in your code! Therefore, it is good coding style, whenever you rely on an implicit superclass constructor call or on a default constructor, to insert a comment noting this fact. Your comments might look like those in the following example:

    class A {
        int i;
        public A() {
            // Implicit call to super(); here.
            i = 3;
        }
    }
    class B extends A {
        // Default constructor: public B() { super(); }
    }

If a class does not declare any constructor, it is given a `publicly` constructor by default. Classes that do not want to be publically instantiated, should declare a `protected` constructor to prevent the insertion of this `public` constructor. Classes that never want to be instantiated at all should define a `private` constructor.

### Finalizer Chaining?

You might assume that since Java chains constructor methods that it also automatically chains the finalizer methods for an object. In other words, you may think that the finalizer method of a class automatically invokes the finalizer of its superclass. In fact, Java does not do this. In practice, finalizer methods are relatively rare, and the need for finalizer chaining rarely arises. If a class `B` with a finalizer method is a subclass of a class `A` with its own finalizer method, then `B`'s finalizer should be sure to invoke `A`'s finalizer, explicitly creating a chain of finalizers. This is a little tricky, since finalizers always have the same name (`finalize()`), and we haven't yet learned how to invoke a method in the superclass when that method is also defined in the subclass. We'll return to the issue of finalizer chaining when we learn how.

### Shadowed Variables

Suppose that our `GraphicCircle` class has a new variable that specifies the resolution, in dots per inch, of the `DrawWindow` object in which it is going to be drawn. And further, suppose that it names that new variable `r`:

    public class GraphicCircle extends Circle {
        Color outline, fill;
        float r;  // New variable.  Resolution in dots-per-inch.
        public GraphicCircle(double x, double y, double rad, Color o, Color f) {
            super(x, y, rad); outline = o; fill = f;
        }
        public void setResolution(float resolution) { r = resolution; }
        public void draw(DrawWindow dw) { dw.drawCircle(x, y, r, outline, fill); }
    }

Now, with this resolution variable declared, when we use the variable `r` in the `GraphicCircle` class, we are no longer referring to the radius of the circle. The resolution variable `r` in `GraphicCircle` shadows the radius variable `r` in `Circle`. [8]

> [8] This is a contrived example, of course--we could simply rename the variable and avoid the issue. Typically we would rename the variable: variable shadowing is a necessary part of Java syntax, but is not a useful programming technique. Your code will be easier to understand if you avoid shadowed variables.

So, how can we refer to the radius variable defined in the `Circle` class when we need it? Recall that using a variable, such as `r`, in the class in which it is defined is shorthand for:

    this.r  // Refers to the GraphicCircle resolution variable.

As you might guess, you can refer to a variable `r` defined in the superclass like this:

    super.r  // Refers to the Circle radius variable.

Another way you can do this is to cast `this` to the appropriate class and then access the variable:

    ((Circle) this).r

This cast is exactly what the `super` keyword does when used like this. You can use this casting technique when you need to refer to a shadowed variable defined in a class that is not the immediate superclass. For example, if `C` is a subclass of `B`, which is a subclass of `A`, and class `C` shadows a variable `x` that is also defined in classes `A` and `B`, then you can refer to these different variables from class `C` as follows:

    x                // Variable x in class C.
    this.x           // Variable x in class C.
    super.x          // Variable x in class B.
    ((B)this).x      // Variable x in class B.
    ((A)this).x      // Variable x in class A.
    super.super.x    // Illegal; does not refer to x in class A.

Note that you cannot refer to a shadowed variable `x` in the superclass of a superclass with `super.super.x`. Java does not recognize this syntax.

### Shadowed Methods?

Just as a variable defined in one class can shadow a variable with the same name in a superclass, you might expect that a method in one class could shadow a method with the same name (and same arguments) in a superclass. In a sense, they do: "shadowed" methods are called overridden methods. But method overriding is significantly different than variable shadowing; it is discussed in the sections that follow.

Object Destruction |  | Overriding Methods