Inheritance Hierarchies¶
If you have multiple subclasses that inherit from a superclass, you can form an inheritance hierarchy. Every subclass is-a or is a kind of the superclass. For example, here is an inheritance hierarchy of Shapes. Square is-a Rectangle and a subclass of Rectangle. Rectangle is-a Shape and a subclass of Shape. In Java, the class Object is at the top of hierarchy. Every class in Java inherits from Object and is-an Object.
One of the main reasons to use an inheritance hierarchy is that the instance variables and methods from a superclass are inherited and can be used in a subclass without rewriting or copying code.
10-5-1: What variables and methods might be inherited from the superclass Shape in the inheritance hierarchy above?
10-5-2: Can you make a 3 level inheritance hierarchy for living things on Earth?
Superclass References¶
A superclass reference variable can hold an object of that superclass or of any of its subclasses. For example, a Shape reference variable can hold a Rectangle or Square object. (This is a type of polymorphism which will be defined in the next lesson).
// The variables declared of type Shape can hold objects of its subclasses
Shape s1 = new Shape();
Shape s2 = new Rectangle();
Shape s3 = new Square();
Notice that the opposite is not true. You cannot declare a variable of the subclass and put in a superclass object. For example, a Square reference cannot hold a Shape object because not all Shapes are Squares. The code below will give an “Incompatible types: Shape cannot be converted to Square” error (although you could use a type-cast to get it to be a (Square)).
// A subclass variable cannot hold the superclass object!
// A Square is-a Shape, but not all Shapes are Squares.
// Square q = new Shape(); // ERROR!!
Why is using a superclass reference for subclass objects useful? Because now, we can write methods with parameters of type Shape or have arrays of type Shape and use them with any of its subclasses as seen in the next sections.
- Person p = new Person();
- This declares and creates an object of the same class Person.
- Person p = new Student();
- This is allowed because a Student is-a Person.
- Student s = new Student();
- This declares and creates an object of the same class Student.
- Student s = new Person();
- This is not allowed because a Person is not always a Student.
10-5-3: A class Student inherits from the superclass Person. Which of the following assignment statements will give a compiler error?
Superclass Method Parameters¶
Another advantage of an inheritance hierarchy is that we can write methods with parameters of the superclass type and pass in subclass objects to them. For example, the print(Shape) method below could be called with many different Shape subclasses and work for Rectangles, Squares, etc.
// This will work with all Shape subclasses (Squares, Rectangles, etc.) too
public void print(Shape s)
{
...
}
Notice that in the Tester class, the print method has a parameter of type Person, but it can be called with Student or Person objects in the main method. Which toString() method is called? It depends on whether a Person or Student is passed in at runtime. What would happen if you commented out the Student toString() method? Which one would be called now?
Which toString() method is called? What would happen if you commented out the Student toString() method? Which one would be called now?
- 10-5-4: Which of the following reasons for using an inheritance hierarchy are valid?
Object methods from a superclass can be used in a subclass without rewriting or copying code.
Objects from subclasses can be passed as arguments to a method that takes an argument of the parent type.
Objects from subclasses can be stored in the same array of the parent type.
All of the above
None of the above
- V
- In fact, all of the reasons listed are valid. Subclasses can reuse object methods written for superclasses without code replication, subclasses can be stored in the same array when the array is declared to be of the parent type, and objects of subclasses can passed as arguments of the superclass type. All of which make writing code more streamlined.
- IV
- All of these are valid reasons to use an inheritance hierarchy.
- I and II
- III is also valid. In some cases you might want to store objects of subclasses together in a single array declared to be of the parent type, and inheritance allows for this.
- I and III
- II is also valid. In some cases a single method is applicable for a number of subclasses, and inheritance allows you to pass objects of the subclasses to the same method if it takes an argument of the parent type, instead of writing individual methods for each subclass.
- I only
- I and III are also valid, in some cases a single method is applicable for a number of subclasses, and inheritance allows you to pass all the subclasses to the same method instead of writing individual methods for each subclass and you might want to store subclasses together in a single array, and inheritance allows for this.
Summary¶
An inheritance hierarchy of subclasses inheriting from superclasses can be formed with Object being the top of the hierarchy.
When a class S “is-a” class T, T is referred to as a superclass, and S is referred to as a subclass.
If S is a subclass of T, then a reference of type T can be used to refer to an object of type T or S. This is called polymorphism, defined more in the next lesson.
Declaring references of type T, when S is a subclass of T, is useful in the declaring formal method parameters of type T, arrays of type T[], and ArrayList<T> of type T so that all the subclasses of T can also be used with these.