7.1. Introduction

Before we get into the details of inheritance, let’s think about the type of problem it can help us solve. You may want to take a moment to quickly refresh your knowledge of UML Class Diagrams before moving on.

Test Yourself

Imagine your boss provides you with the UML diagram below and asks you to write the code for the two classes in the cs1302.inheritance package.

  1. Take a moment to identify (not fix) the instance variables and methods that will be identical in both classes. You should see a high degree of overlap. Write these redundancies in your notes. Remember: as a general rule, we want to eliminate redundant code to cut down on the number of potential bugs and help readability.

  2. If we added an interface, call it Drivable, could that help us eliminate this type of redundancy?

hide circle
set namespaceSeparator none
skinparam classAttributeIconSize 0

package "cs1302.inheritance" {
   class Vehicle {
     -make: String
     -year: int
     +<<new>> Vehicle(make: String, year: int)
     +getMake(): String
     +getYear(): int
   }

   class Car {
     -make: String
     -year: int
     -numDoors: int

     +<<new>> Car(make: String, year: int,
     \t\t\tnumDoors: int)
     +getMake(): String
     +getYear(): int
     +getNumDoors(): int
   }
}

Test Yourself Solution (open after attempting question above)

In this example, variables make and year are redundant along with methods getMake() and getYear(). In fact, those methods will contain the exact same code in both classes.

Unfortunately, interfaces cannot help here. Interfaces help us cut down on redundant code when we call (use) these classes but it won’t cut down on redundant code across the class definitions. We would benefit from the polymorphism and type compatibility that comes with using an interface but that would benefit us when using these classes. It would not cut down on the amount of code required to create these classes.

Don’t worry, this is where inheritance comes in!

In its simplest terms, inheritance in Java is a way to create a new class based on an existing class without the need to manually copy-paste the source code. Using inheritance, Car can inherit the methods and instance variables of Vehicle resulting in the UML diagram below:

hide circle
set namespaceSeparator none
skinparam classAttributeIconSize 0

package "cs1302.inheritance" {

   Vehicle <|--right Car: extends (is-a)
   class Vehicle {
     -make: String
     -year: int
     +<<new>> Vehicle(make: String, year: int)
     +getMake(): String
     +getYear(): int
   }

   class Car {
     -numDoors: int

     +<<new>> Car(make: String, year: int,
     \t\t\tnumDoors: int)
     +getNumDoors(): int
   }
}

Compare the second version of the UML class diagram to the first one. Notice how much smaller the Car class is now. Instead of copy/pasting methods and instance variables, we simply add the inheritance (extends) relationship and everything from Vehicle is automatically copied into Car.

Note

The functionality of the Car class has not changed! We can still call getMake() and getYear() using a Car reference even though those methods aren’t explicitly defined in the Car class. That’s because they are inherited!

It’s also worth noting that the direction of the relationship matters! If you are ever wondering whether an inheritance relationship is appropriate, a great starting point is asking whether or not the child “is a” parent. You may hear of this referred to as the (is-a test). Try it in the example above. Would you say that a car is a vehicle? Yes! Would you say a vehicle is a car? Well, not necessarily. A vehicle could be a boat, a truck, etc. So, the inheritance relationship would not be appropriate if we reversed it.

Basic Terminology

Here are some terms that you should know related to inheritance in Java.

  • parent class, super class, base class - the original class you want to extend.

  • child class, subclass, derived class - the new class you want to create based on the parent class.

  • class hierarchy - a collection of classes related by inheritance.

As we will see in this chapter, inheritance allows us to avoid redundancy both in the classes we are creating and in the code that uses those classes. When using interfaces, the benefit came only when we used the classes.

Given that inheritance helps in both cases, it may seem like inheritance should always be used over interfaces. However, as we will see soon, each has an important role in software development.

In this chapter, we will see how inheritance allows us to:

  1. Create new (child) classes by extending existing (parent) classes. The child class inherits the instance variables and methods of the existing class which allows us to eliminate redundant code.

  2. Leverage polymorphism to cut down on code that uses the inheritance hierarchy as we did with interfaces.

  3. Add new methods and override inherited methods to give child classes their own unique behaviors that are different from the parent.

Rapid Fire Review
  1. What is the primary benefit of using inheritance in Java?

    1. It allows multiple classes to be combined into one.

    2. It automatically generates new methods for all classes.

    3. It enables the creation of a new class based on an existing class without copying code.

    4. It makes all methods private by default.

  2. In the context of inheritance, what is the term for the class that is being extended? a. Child class b. Interface class c. Super class d. Derived class

  3. Which of the following statements is true about the Car class after adding the extends relationship with Vehicle

    1. A variable of type Car cannot be used to call methods from the Vehicle class.

    2. The Car class must redefine all methods from the Vehicle class.

    3. The Car class inherits the methods and instance variables from the Vehicle class.

    4. The Car contains more lines of code compared to when it didn’t use inheritance.

  4. What does inheritance help eliminate in the code?

    1. All runtime errors.

    2. Redundant code.

    3. The need for classes.

    4. The need for interfaces.

  5. Which term refers to a new class created based on a parent class?

    1. Super class

    2. Interface class

    3. Base class

    4. Child class