10 Mar 1996

Inheritance

On the 12th day of Xmas, my true love gave to me
All that stuff I got the day before, and
12 drummers drumming.

Occasionally an application needs to add additional fields to a class. You don't want to change the original definition of the class unless these fields apply to every possible use of the old class. You don't want to start from scratch and have to recreate all of the logic that already exists to handle the fields in the old class. The solution is to create a class name that extends the original class.

The new class is said to be a subclass of the old class. The old class is its parent. The subclass inherits all the old field variables and methods of its parent, including any fields and methods that the parent class inherited by extended some even older class.

Based on the song, this particular class tree starts with:

Then for each day there is a new class with a new field. Each object of a new class contains all of the field variables of the previous classes. In a sense, an object of the class Sixth_Day_Stuff can also be regarded as being a member of its parent classes First_Day_Stuff through Fifth_Day_Stuff because it has all the necessary fields. A method of Sixth_Day_Stuff can access all the inherited fields as local names:

A reference variable is constrained by its declaration to designate objects of a particular class. Since subclasses have all the necessary fields, a reference variable can be assigned a reference value designating any subclass of its declared class:

In this case, the object designated by gifts has three extra days worth of fields, but it is still a perfectly acceptable instance of Sixth_Day_Stuff because it has geese_a_laying and all the prior fields.

The examples so far have shown only data fields, but methods can be inherited as well. For example:

Now the jewlery_appraisal method can be called using objects of class Fifth_Day_Stuff to Twelfth_Day_Stuff (because they have rings). It cannot in general be called with an object of type Fourth_Day_Stuff.

Instanceof and Casting References

However, object from the later days can be regarded as members of the Fourth_Day_Stuff class, can be used in methods of that class, and can have their reference value assigned to reference variables of the Fourth_Day_Class. So just because an object is only declared to be Fourth_Day_Stuff doesn't mean that it cannot have more stuff, and if it does have more stuff it can be appraised.

The instanceof operation determines if the object designated by a reference to a class is actually a member of a subclass derived from it and has more stuff. The following example assumes that handle_Partridge has been added as a method field of the First_Day_Stuff class, and handle_Turtle_Doves is a method of Second_Day_Stuff, and so on.

Although everything is a method of some class, handle_Birds here is simply a static method, probably of the class containing the main program. It acts as what any other language would call a plain subroutine. It accepts an argument that is a reference to an object of class First_Day_Stuff. Of course, since all of the objects from any of the subsequent days include the partridge_in_a_pear_tree field, this method can be called with objects from any of the subclasses. Thus the handle_Partridge operation is called unconditionally. If the object really is just from the First_Day_Stuff class, then it has no additional fields and it would be a mistake to reference them. However, if the object is from any of the subclasses then the instanceof operation will return true from the test if the object designated by x is also in the Second_Day_Stuff class. In this case, it is possible to call the handle_Turtle_Doves method.

The syntax "(Second_Day_Stuff) x" is called a cast. It converts a value of one type into a value of another type. In this case, "x" is a variable containing values that are references to objects of class First_Day_Stuff, but the cast converts the value to a reference to an object of the subclass Second_Day_Stuff. In this case, the instanceof test has already proven that the cast is valid. In other contexts, however, the Java Interpreter always performs a runtime test when a reference is cast and it raises a runtime exception if the object does not actually belong to the class (or a subclass of the class) mentioned in the cast.

Override

In addition to creating new fields, a new class can define a method with the same name and arguments as a method in the old class. This new method hides the old one and is said to override it.

Assuming that the original Date class was dumb and did not allow February to have 29 days, this class overrides the is_valid method to permit that date. For all other dates, it simply falls back to the original is_valid method by using the special qualification "super.is_valid" which means, "use the method as it was defined in the previous class."

Now there is no particular trick here if some code is using an object that it knows is of class Leap_Year_Date. However, a Leap_Year_Date is also a Date, and an object of type Leap_Year_Date can be used in any expression or method call which expects a plain Date object. If that expression or method calls the "is_valid" method for this object, it will get the version of the method in the Leap_Year_Date. Even though the statement only "knows" that the object is some type of Date, the object itself "knows" that it is really a Leap_Year_Date and that "is_valid" has been overridden.

Narrowing

Object Oriented programming is the only context in which something can be narrowed by extending it. Normally, when you extend something it becomes wider. The opposite is true for Java.

All objects of a class are also members of all its parent classes. Thus objects of type Fifth_Day_Stuff through Twelfth_Day_Stuff are all also members of the class Fourth_Day_Stuff, but the opposite is not true. Thus Fourth_Day_Stuff is a more general category including all the classes derived by extending it. If I take an object that initially appears to be of type Fourth_Day_Stuff, and by examining it determine that it is really of type Fifth_Day_Stuff and has an extra field, then I have more precisely characterized the object to a subset of all possible Fourth_Day_Stuff objects. This increased precision "narrows" the possible shape of the object, but it "extends" the number of fields in the object. This terminology will always be somewhat confusing, but it is possible to eventually get used to it.

Special Cases of Inheritance

The static public fields of a class can always be referenced by preceding the field name by the class name and a period. The instance variables and methods of a class can be called by preceding them with a reference value to an object of the class. All these periods and compound names can get to be tedious. The only way to ditch the periods is make the program you are writing a new method of a new class that extends some old class. You only get to play this trick with one class, so you choose the one with fields representing the variables that you most frequently use.

When a program uses the Graphic User Interface, either because it is an applet in a Web browser or because it uses the Java Abstract Windows Toolkit (AWT), it must supply code to handle the events when the user clicks a mouse button, enters data into a field, or hides and restores the window. The AWT and Applet classes contain methods that are called when such events occur. The user application receives these events by extending these classes and overriding the event-handling methods.

Continue Back PCLT

Copyright 1996 PC Lube and Tune -- Java H. Gilbert

This document generated by SpHyDir, another fine product of PC Lube and Tune.