10.2. Inheritance and Constructors¶
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
}
}
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?
10.2.1. Chain of initialization¶
As you may recall from Unit 5, 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.
- I only
- I is okay but III is also okay.
- I and III
- The MPoint variables are private and they can not be directly accessed in NamedPoint. You can use super as the first line in a constructor to initialize them. If you don't use super as the first line in a constructor one will be put there by the compiler that will call the parent's no argument constructor.
- II only
- II is invalid. Children do not have direct access to private fields. You can use super in a constructor to initialize these by calling the parent's constructor with the same parameter list.
- III only
- I is also okay
9-2-2: 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;
}
You can step through this code using the Java Visualizer by clicking the following link Named Point.
10.2.2.
Programming Challenge : Square is-a Rectangle¶
In this challenge, you are giving 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.
Make the class
Square
below inherit fromRectangle
Add a
Square
constructor with 1 argument for a side that callsRectangle
‘s constructor with 2 arguments usingsuper
.Uncomment the objects in the
main
method to test drawing the squares.Add an
area
method toRectangle
that computes the area of the rectangle. Does it work forSquare
s too? Test it.Add another subclass called
LongRectangle
which inherits fromRectangle
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).
Make the class
Square
below inherit fromRectangle
.Add a
Square
constructor with 1 argument for a side that callsRectangle
‘s constructor with 2 arguments usingsuper
.Uncomment the objects in the
main
method to test drawing the squares.Add an
area
method toRectangle
that computes the area of the rectangle. Does it work forSquare
s too? Test it.Add another subclass called
LongRectangle
which inherits fromRectangle
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).
For a more complex example of drawing shapes, try running this replit Java Swing code (or download the files here by clicking on Download on the top right and use the files in your own Java IDE). When the yellow panel comes up, click on either the Rectangle or the Oval button and then click and drag somewhere on the yellow panel to draw that shape. Take a look at the Rectangle.java and Oval.java files to see how they inherit from the Shape class in Shape.java. Java Swing graphical programming is not covered on the AP CSA exam, but it is a lot of fun!
10.2.3. 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 tosuper
an implicit call tosuper()
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 theObject
constructor.