Chapter 13

Inheritance

Put simply, Inheritance allows you to reuse code that you have already written in another class.

Suppose, for example, you have written an application in which you have created a class called Employee. Perhaps you have created instance variables for the employee's name, social security number, and position. You now wish to create another class called SalariedEmployee. But a SalariedEmployee is just an Employee whose earnings are fixed. Will you have to start from scratch? Wouldn’t it be convenient to use all of the code from the Employee class within your new SalariedEmployee class? This is the purpose of inheritance.

By writing

public class SalariedEmployee extends Employee

we are saying (via the extends keyword), “create a class called SalariedEmployee that already has all the data and functionality of the Employee class.” So, a SalariedEmployee object would already have a name, social security, and position field. The Employee class in this scenario is called the superclass (or parent class or base class) and SalariedEmployee would be called a subclass (or child class or derived class, respectively).

Any (non-private) method from the Employee class can be applied to a SalariedEmployee object. Any additional code that you write in the SalariedEmployee class will be specific to the class. For example, you would likely add a field called salary and a method called setSalary() . These methods would not apply to an Employee. You can also override methods from the Employee class. For example, suppose the Employee class has this (admittedly not very useful!) method:

public void sayTitle()
{
  System.out.println("I am an employee");
}

and the SalariedEmployee has this method:

public void sayTitle()
{
  System.out.println("I am a salaried employee");
{

Because this method in the SalariedEmployee class has the exact same signature (header) as the method in the Employee , its code will override (i.e., supercede) the code in Employee . In general, if the child and parent classes both have a method with the same header/signature, the child method will be executed for any instance of the child class. To see how this works, consider the following code snippet (assume that the necessary constructors exist)

Employee emp = new Employee();
SalariedEmployee salEmp = new SalariedEmployee();
emp.sayTitle();
salEmp.sayTitle();

will produce the output

I am an employee

I am a salaried employee

You might also need a class for commissioned employees. Once again, a CommissionedEmployee is just a more specific type of Employee , so the CommissionedEmployee could also extend the Employee class.

Note that a class can have multiple children (subclasses), but each class can have only one superclass. However, that superclass may itself inherit code from another class, which may extend another, and so on. For example, if Employee extends Person, CommissionedEmployee inherits not only from Employee, but also (indirectly) from Person.

The protected keyword

Private variables in the superclass are not visible from the child class, even though objects of the child class contain this data. One way to address this problem is for methods in the child class to use getter (accessor) methods in the parent class to access data. Another is to use the protected keyword. Anything set to protected in the superclass is visible by sub-classes (and other classes in the same package).

The super keyword

super is used in the child class to explicitly refer to a method of the parent class.

There are two common uses for this:

The subclass constructor automatically calls the default (i.e., no parameters) constructor of the superclass. However, to pass values to the superclass constructor, use the super keyword, as shown in this example:

//superclass (parent class)
public class Furniture{
  //constructor
  public Furniture(double weight){
    this.name = name;
  }

}
//subclass (child class)
public class Chair{
  //constructor
  public Chair(double weight, boolean hasArms){
    //call the Furniture constructor and pass in the weight
    super(weight); //note that we now have a Furniture object created
    //set the data specific to the Chair
    this.hasArms = hasArms;
  }

}



To call a method from the superclass, write super.[method name]. See the following example. The toString method for Chair first calls the Furniture toString method, then adds a phrase to say whether or not it has arms.

//in the Furniture class
//returns a String with information about the Furniture object
public String toString(){
  return "This piece of furniture weighs " + weight " + " pounds";
}
//in the Chair class
//returns a String with information about the Chair object
public String toString(){
  String arms;
  if (hasArms)
    arms = "does";
  else
    arms = "does not"
  return (super.toString() + "and " + arms + " have arms"};
}

Given an obect of type Chair, invoking its toString() method would produce something like:

This piece of furniture weighs 31 pounts and does not have arms.

The Object class

We mentioned earlier that a superclass can itself extend another class, which in turn can extend another. Here's an example of this from the documentation for the JOptionPane class (which creates a pop-up dialog window).

JOptionPane inheritance diagram

Notice how JOptionPane extends JComponent, which extends Container, which extends Component.

This means that not only can a JOptionPane object invoke all methods defined in the JOPtionPane class, but also all (non-private) methods in these other classes. The snippet below (also from the documentation) shows this

Ineritance of methods

At the very top (and this is true for all classes in Java) is Object. A consequence of extending Object is that all classes inherit a toString method (used in the earlier example for the super keyword) that returns a String for representing the object, which is used by System.out.println. The default behavior of the toString method is to print something like

Object@1e81f4dc

Overriding the toString method allows you to print something more descriptive. There are other methods inherited from Object, as well, which are listed here.

Polymorphism

In the Chair class example above, note that creating a Chair object also creates a Furniture object (we say a Chair "is a" Furniture). So, one object can act as both a Chair and a Furniture. When we invoke a method on a Chair object, if that method is found in the Chair class, that code will be applied. Otherwise, the code from the Furniture class is applied (or the superclass of Furniture, if it's still not found there). This concept is called polymorphism because the same method has "many forms."

Inheritance creates what is called an "is-a" relationship between an instancd of the subclass and the superclass. This should not be confused with the "has-a" relatinship created when one class creates an instance of another (for example, if the Furniture class had an instance variable of type AssemblyInsrtuctions-- where AssemblyInstructions is another class).

Abstract Classes

Abstract classes are designed to be parent classes, but not to be instantiated themselves. Some methods have code, but at least one method does not-- the child class is expected to provide the code. An abstract class is like a template for the child classes.

In the example below, we see that the speak and move methods are declared in Pet, but no code is provided. Because of this, you cannot instantiate the Pet class. Note how the Cat class provides the code for the abstract methods from Pet. Cat is not abstract-- you can create a Cat object.

You might be wondering why Pet has a constructor, if it is abstract. This is because a Cat “is-a” Pet, so in order for Cat to inherit data and methods from Pet, a constructor must exist in Pet to create those.

public abstract class Pet
{
  protected String name;
 
  public Pet(String petName){
    name = petName;
  }
 
  public String getName(){
    return name;
  }
 
  public String toString(){
    return "pet " + name;
  }
 
  abstract public String speak();
 
  abstract public String move();
}
public class Cat extends Pet{
  private int weight;
 
  public Cat(String catName, int catWeight){
    super(catName);
    weight = catWeight;
  }
 
  public String toString(){
    return super.toString() + " is a " + weight + " lb. cat";
  }
  public String speak(){
    return ("meow, my name is"+super.getName());
  }
  public String move(){
    return "tiptoe";
  }
}



Interfaces

A class where all methods are abstract is called an interface. An interface is declared as

public interface interfaceName

Methods headers (declarations) are stated, but no code is provided. An interface guarantees that a class will implement these methods. Think of an interface as a "to-do" list of methods. Since there's no code, a child class doesn't "extend" an interface, rather "implements" it.

Comparing the implements keyword to extends :

extends = has all the code from the (parent) class

implements = provides code required by the interface.

When to use which

An abstract class is typically used for an object that is application-specific (only applies to the program you’re working on), but is incomplete without its subclasses.

An interface has suitable methods for your program but would be equally applicable in a variety of programs.

UML Diagrams

Universal Modeling Language (UML) diagrams show the relationships among classes and interfaces in an application. You will see some variation in how these are constructed, but in general: