Skip to main content

Section 12.2 Subclasses and Inheritance

One option is to make it so that every Course object is also a Grade object. We can do this by making a subclass, also sometimes called a derived class.
A subclassB of a class A makes it so that its objects inherit all the properties and methods of objects of class A. Objects of the subclass are also objects of the superclass. We say B extends A, or that B is derived from A. To accomplish this, class B needs to indicate that it extends class A, and its constructor must call class A’s constructor.
For example, we can create a Course class as follows:
public class Course extends Grade {
  String prefix;
  int number;

  Course(String prefix, int number, String letterGrade) {
    super(letterGrade);
    this.prefix = prefix;
    this.number = number;
  }
}
So the first thing that you see is the phrase extends Grade. We have seen implements ... before, and this works similar but for classes. That actually makes a huge difference, because classes have implementations of behavior, and by extending a class we are burdened by those implementations. Also unlike with interfaces, of which you can implement many, you can only ever extend one class.
You may not have known or really care about this before, but there is always an implicit extends Object present in every class, if we don’t make it extend some other class instead. Thus the Object class is the ancestor for all classes in Java.
The next thing you will notice is the super(letterGrade) call. This is the call that reaches to the constructor of Grade, so that that constructor can do its thing. This is important, as a Course object is supposed to be a fully functioning Grade object, on top of whatever else it is, and in order to ensure that we need to run the Grade class’ constructor. And it must be the first thing in the subclass’ constructor.
Now let’s take a look at a piece of code that uses a Course object:
Course c = new Course("CS", 121, "B+");
c.prefix;        // c is a Course
c.getCredits();  // c is also a Grade!
Once we make a Course object, we can access any properties and methods of the Course class that we should have access to, like prefix above, but we can also access anything that we could access if we had a Grade object: Every Course object is a bona fide Grade object and can be used as such. Objects of a subclass can act as objects of its superclass. And we can do that without having to add any extra code, beyond the extends ... line.
This may sound strange at first, but let’s consider an analog for a second. I am going to assume that you are a student enrolled at a college or university. You are also a person, and we could say in a way that your Student status extends that of your Person status, as every student is in fact a person. As a person we can ask you for your first and last name, or your gender and preferred pronouns; if we are your parents we can tell you to brush your teeth or wash your hands, and so on. You don’t lose any of these properties because you are a student, but you gain some new ones, like a student ID number and credentials, a list of courses you are enrolled in, your financial aid record, meal plan, what have you. There are things that every person has, and things only students have. We might represent this situation in code by having two classes, one called Student and one called Person, and the Student class extends/derives from the Person class.
This is the essence of our first mechanism for object behavior extension, namely inheritance:
Inheritance is the feature of a programming language that allows objects of a subclass to inherit all the properties and methods of the superclass.
Inheritance provides a very strong compile time binding of these properties to the object. Every object of the superclass will be having this relation to the objects of the superclass and that cannot change without a recompilation of the program. In an inheritance setting we have one object that has two classes and therefore has acquired the behavior of both classes.