5.2 Inheritance and Constructors

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

Java1 class period2 exercises7 graded tests

Files

README.mdDownload

5.2 Inheritance and Constructors

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.

Subclasses inherit public methods from the superclass that they extend, but they cannot access the private instance variables of the superclass directly. And subclasses do not inherit constructors from the superclass. But inherited instance variables need to be properly initialized or none of the inherited methods are likely to work properly, so how can a subclass initialize the superclass’s private variables?

If the super class provides public setter methods for those variables the subclass could use those. But that won’t always be the case. And sometimes constructors do more complex initialization than just setting variables.

The way out is provided by the keyword super. When used like the name of a method, i.e. when followed with parentheses and arguments, super provides a way to call the code in a superclass constructor, passing whatever arguments it needs. But unlike when we call a constructor with new, a call to super doesn’t create a new object. Instead it runs the constructor’s code in the context of the object currently being constructed. This lets the superclass constructor initialize the instance variables declared in the superclass including private variables the subclass can’t directly access.

It’s critical that all the instance variables in an object be properly initialized before the object is used, including by code in the rest of the constructor. To ensure that, if the constructor doesn’t start with a call to super Java will automatically insert a call to super with no arguments. (That means if the superclass does not have a no-argument constructor that the subclasses will have to explicitly call super with the appropriate arguments for some constructor that does exist. This ensures that instances of the subclass are properly initialized.)

For example the call to super(theName) in Employee below runs the code in the Person constructor that takes a String argument which presumably initializes an instance variable in the Person class to hold the name.

public class Employee extends Person
{
    public Employee(String theName)
    {
        super(theName); // calls Person(String) constructor
    }
}

Exercise 1

Try creating another Employee object in the main method that passes in your name and then use the get methods to print it out. Which class constructor sets the name? Which class constructor sets the id?

Open the 01-InitPrivateInherited folder and edit Employee.java. Press Run to try it; Run Tests checks it (2 tests).

Chain of initialization

As you may recall from Unit 3, if you do not write a constructor your class will automatically get a default no-argument constructor. In addition to initializing all instance variables to the default value for their type, the default no-argument constructor calls the superclass’s no-argument constructor.

This means you can only write a class with a default no-argument constructor if its superclass has a no-argument constructor. If you are extending a class without a no-argument constructor but you want your class to have a no-argument constructor you will need to explicitly write one and use super to call an existing constructor on the superclass with appropriate arguments.

However it is created, explicitly or implicitly, the chain of super calls from each subclass to its superclass ends in the no-argument constructor of java.lang.Object. This is a special class defined in Java which is the superclass of any class that doesn’t explicitly extend some other class and the only class with no superclass and thus no super constructor that needs to be called.

Once the chain reaches the top, at Object it starts unwinding, with first the Object constructor code running, then the constructor from its subclass, and so on until finally the constructor of the actual class being constructed runs. At that point any inherited instance variables will have been initialized so the constructor can safely call inherited methods that depend on those variables.

Check your understanding: Given the class definitions of MPoint and NamedPoint below, which of the constructors that follow (labeled I, II, and III) would be valid in the NamedPoint class?

class MPoint
{
   private int myX; // coordinates
   private int myY;

   public MPoint( )
   {
      myX = 0;
      myY = 0;
   }

   public MPoint(int a, int b)
   {
      myX = a;
      myY = b;
   }

   // ... other methods not shown

}

public class NamedPoint extends MPoint
{
   private String myName;
   // constructors go here
   // ... other methods not shown
}

//  Proposed constructors for this class:
I.   public NamedPoint()
     {
        myName = "";
     }
II.  public NamedPoint(int d1, int d2, String name)
     {
        myX = d1;
        myY = d2;
        myName = name;
     }
III. public NamedPoint(int d1, int d2, String name)
     {
        super(d1, d2);
        myName = name;
     }

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

You can step through this code using the Java Visualizer by clicking the following link Named Point.

Coding Challenge: Square is-a Rectangle

In this challenge, you are given a class called Rectangle that has two instance variables, length and width, a constructor that initializes them, and a method called draw that uses nested loops to draw a length x width rectangle of stars. Try it out below.

You will write a new class called Square that inherits from Rectangle. Is a square a rectangle? Yes! A square is a rectangle where the length and width are equal. Square will inherit length, width, and the draw method. You will write Square constructors that will call the Rectangle constructors.

Exercise 2
  1. Make the class Square inherit from Rectangle
  2. Add a Square constructor with 1 argument for a side that calls Rectangle’s constructor with 2 arguments using super.
  3. Uncomment the objects in the main method to test drawing the squares.
  4. Add an area method to Rectangle that computes the area of the rectangle. Does it work for Squares too? Test it.
  5. Add another subclass called LongRectangle which inherits from Rectangle but has the additional condition that the length is always 2 x the width. Write constructors for it and test it out. Do not make it public (because only 1 class per file can be public).

Open the 02-challenge-5-2-Square-Rectangle folder and edit Square.java. Press Run to try it; Run Tests checks it (5 tests).

Summary

  • Subclasses do not have access to the private instance variables in a superclass that they extend.
  • Constructors are not inherited.
  • A superclass constructor must be called from the first line of a subclass constructor by using the keyword super and passing appropriate parameters. If there is no explicit call to super an implicit call to super() will be added by the Java compiler.
  • The actual parameters passed in the call to super provide values that the superclass constructor can use to initialize the object’s instance variables.
  • Regardless of whether the superclass constructor is called implicitly or explicitly, the process of calling superclass constructors continues until the Object constructor is called. At this point, all of the constructors within the hierarchy execute beginning with the Object constructor.

For teachers

5.2 Inheritance and Constructors

Students read CSAwesome2's “Inheritance and Constructors” in CS Room and work through its 2 Java coding exercises.

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

Goals

  • Subclasses do not have access to the private instance variables in a superclass that they extend.
  • Constructors are not inherited.
  • A superclass constructor must be called from the first line of a subclass constructor by using the keyword super and passing appropriate parameters. If there is no explicit call to super an implicit call to super() will be added by the Java compiler.
  • The actual parameters passed in the call to super provide values that the superclass constructor can use to initialize the object’s instance variables.
  • Regardless of whether the superclass constructor is called implicitly or explicitly, the process of calling superclass constructors continues until the Object constructor is called. At this point, all of the constructors within the hierarchy execute beginning with the Object constructor.

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–02, 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-InitPrivateInheritedEmployee.javaAutograded2
02-challenge-5-2-Square-RectangleSquare.javaAutograded5

Teachers can download a reference solution after signing in.