5.5 Inheritance Hierarchies

From CS Awesome 2CC BY-NC-SA 4.0Original page

Java1 class period3 exercises10 graded tests

Files

README.mdDownload

5.5 Inheritance Hierarchies

Each coding exercise has its own folder. Open its .java file and press Run to try it. Run Tests checks every graded exercise in this lesson at once.

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.

An Inheritance Hierarchy of Shapes

An Inheritance Hierarchy of Shapes

One of the main reasons to use an inheritance hierarchy is that all the classes in the hierarchy can be treated as instances of the top type in the hierarchy. This is called polymorphism and we’ll discuss it in more detail in the next section.

Inheritance can also reduce code duplication since common behaviors can be defined in methods in a superclass and inherited by all their subclasses. But you should never use inheritance just to reuse code if there isn’t a true “is-a” relationship between the subclass and the superclass.

What variables and methods might be inherited from the superclass Shape in the inheritance hierarchy above?

Discuss this with your class, or answer it on CS Awesome: https://runestone.academy/ns/books/published/csawesome2/topic-5-5-hierarchies.html#hierarchy1

Can you make a 3 level inheritance hierarchy for living things on Earth?

Discuss this with your class, or answer it on CS Awesome: https://runestone.academy/ns/books/published/csawesome2/topic-5-5-hierarchies.html#hierarchy2

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.

// 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.

Check your understanding: A class Student inherits from the superclass Person. Which of the following assignment statements will give a compiler error? — answer it on CS Awesome: https://runestone.academy/ns/books/published/csawesome2/topic-5-5-hierarchies.html#qinherRef

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 following code, 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 toString method in Student? Which one would be called now?

Exercise 1

Which toString() method is called below? What would happen if you commented out the Student toString() method? Which one would be called now?

Open the 01-superclassMethod folder and run Tester.java. It is an example, so it has no tests.

Superclass Arrays and ArrayLists

Using inheritance hierarchies, we can create arrays and ArrayLists using the superclass type and put in values that are of the subclass types. This can be very useful! For example, here is some code that creates a Shape[] array and an ArrayList<Shape>, both of which can hold any objects of Shape and any of its subclasses.

// This shape array can hold the subclass objects too
Shape[] shapeArray = { new Rectangle(), new Square(), new Shape() };

// The shape ArrayList can add subclass objects too
ArrayList<Shape> shapeList = new ArrayList<Shape>();
shapeList.add(new Shape());
shapeList.add(new Rectangle());
shapeList.add(new Square());

The code below has an ArrayList<Pet> that can hold Pet or Dog objects. Notice that the loop works with a variable of type Pet because a Dog is a Pet too!

Exercise 2

Scroll down to look at the Dog class and add a similar Cat class that extends Pet. Don’t make the Cat class public because there can only be 1 public class in a file. Scroll back to the main method and add some Cat objects to the ArrayList too. Does the petList work with Cats too?

Open the 02-superclassArray folder and edit Pet.java. Press Run to try it; Run Tests checks it (4 tests).

Check your understanding: Which of the following reasons for using an inheritance hierarchy are valid?

  • I. Object methods from a superclass can be used in a subclass without rewriting or copying code.
  • II. Objects from subclasses can be passed as arguments to a method that takes an argument of the parent type.
  • III. Objects from subclasses can be stored in the same array of the parent type.
  • IV. All of the above
  • V. None of the above

Answer it on CS Awesome: https://runestone.academy/ns/books/published/csawesome2/topic-5-5-hierarchies.html#qoo_4

Coding Challenge: Shopping Cart

Shopping

The following code contains a class called ShoppingCart that simulates a grocery store or an online store's shopping cart. It has an ArrayList called order that you can use to add Items to the shopping cart. The Item class keeps track of the name and the price of each Item. If you run the code below, you will see that it adds 2 items to the cart and then prints out the total order.

In this challenge, you will add a new class called DiscountedItem that extends the Item class. The ArrayList of Item will still work since it can hold the subclasses of Item too! The ShoppingCart printOrder method will work with Item and DiscountedItem but note that it has an if statement that treats DiscountedItem differently.

In the DiscountedItem subclass,

  1. Add an instance variable for the discount amount.
  2. Add constructors that call the super constructor Item.
  3. Add get/set methods for discount. The get method is given below but you should modify it.
  4. Add a toString method that returns a string that includes a call to the super toString method that will print out the price as well as the discount amount using the super.valueToString() method to format it. You could put the discount in parentheses with a minus sign in front of it like “(- $.50)”.
  5. Uncomment the code in the main method to test adding DiscountedItems to the cart.
Exercise 3

Complete the class DiscountedItem that inherits from Item and adds an discount instance variable with a constructor, get/set, and a toString method. Uncomment the testing code in main to add discounted items to the cart.

Open the 03-challenge-9-5-shopping folder and edit Tester.java. Press Run to try it; Run Tests checks it (6 tests).

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.

For teachers

5.5 Inheritance Hierarchies

Students read CSAwesome2's “Inheritance Hierarchies” in CS Room and work through its 3 Java coding exercises (2 graded, 1 example).

  • Time: 1 class period
  • Tests: 10 in 2 graded exercises, set up for you when you import the lesson

Goals

  • 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.

Before class

In class

  1. Students read README.md. Questions that need CS Awesome's interactive widgets link back to it.
  2. Students do exercises 01–03, each in its own folder, pressing Run to try their code.
  3. Run Tests checks every graded exercise at once; scores appear in the Gradebook. Grading uses your copy of the tests, so a student who edits theirs does not change the grade.

Exercises

FolderFileGradingTests
01-superclassMethodTester.javaExample, not graded0
02-superclassArrayPet.javaAutograded4
03-challenge-9-5-shoppingTester.javaAutograded6

Teachers can download a reference solution after signing in.