Inheritance in Java: A refresher

Inheritance is the capability of a class to use the properties and methods of another class while adding its own functionality. An example of where this could be useful is with an employee records system. You could create a generic employee class with states and actions that are common to all employees. Then more specific classes could be defined for salaried, commissioned and hourly employees. The generic class is known as the superclass and the specific classes as subclasses. A subclass is a more specialized form of the superclass. It  satisfies all of the basic requirements of the superclass but adds on or extends the super class in some way. The concept of inheritance greatly enhances the ability to reuse code as well as make design a much simpler and cleaner process.

Extending A Class

When we wish to implement a subclass, we specify the class that we are inheriting from by using the keyword extends. A template of this is provided below:

modifier class subClassName extends superClassName {
...
}

Java does not support multiple inheritance, or inheritance from multiple superclasses, so at most one class can be listed after the extends keyword. Any class can be extended as long as that class is not declared final. There is no limit on the number of times a certain class can be extended. For example, a Movie class could have subclasses Drama, Action and Comedy but it's not valid for a Drama class to extend both a Movie class as well as some other class such as Theatre

When a class is extended, the visibility rules are still enforced. This means a subclass cannot access the private members of any of its superclasses but it can access both the public and protected attributes and operations from the class that it extends. Constructors, which are not considered members of a class, are not inherited by a subclass. When we wish to access an attribute or operation that is only present in a superclass we use the keyword super. super provides a reference to the superclass much the same way that the keyword this provides a reference to the current class.  super can also be used to call the superclass's constructor. This will only work within the definition for the subclass's constructor and it must be present as the very first line of the definition. For instance, if we wish to define a Drama class constructor which calls Movie's constructor we could do something similar to this:

public class Drama extends Movie {

	protected string dramaDescription;
 
	public Drama( string title, string description)
	{
		super( title );
		dramaDescription = description;
	}
 }

This calls Movie's constructor and then sets the dramaDescription variable. When super is not used within a constructor for a subclass, Java will attempt to call the default constructors for each superclass starting with the highest class and going down to the current subclass.

Inheritance increases the number of classes that need to be searched when you attempt to access a variable or a method. Java will search the local scope first, then check the class scope and then check each superclass starting at the bottom and then working up to its root. If a variable with the same name is declared in several scopes, the first one found is used. This allows a subclass to override superclass methods. By simply providing an implementation for a method with the same signature as that in the superclass we can easily override the superclass's implementation of that method. Every time that method is called within an object of the subclass type, the subclass's definition is used rather than the superclass's. It is still possible to access the superclass's version of the overridden method by using the super keyword.

There are times when you may not want a class to be extended or you may not want a particular method in a superclass to be overridden. In these cases we use the final keyword. The final keyword does not allow a class to be extended if it is placed before the class keyword in the class declaration. If we wish to stop a particular method from being overridden we place thefinal keyword before the return type in the method definition.

Abstract Classes

An abstract class is a class that leaves one or more method implementations unspecified by declaring one or more of its methods abstract or by not providing an implementation for an abstract method inherited from a superclass or interface. An abstract method has no body (i.e., no implementation). A concrete subclass is required to override the abstract method and provide an implementation. Hence, an abstract class provides implementations for some methods while leaving others to be defined solely by its subclasses. Abstract classes cannot be instantiated; they exist so that other classes can extend them.

For instance, if we wish to create a Shape class as the basis for creating different types of shapes to draw to the screen, it may be beneficial to create Shape as an abstract class. It doesn't make sense to draw an object of type Shape without having more information about it, such as the number of sides, therefore we make Shape abstract. Since we wish to define the draw method of Shape differently for each shape, we define the method draw to be abstract. Being an abstract method also ensures that the method draw is defined for each subclass of Shape. This in turn ensures that all future subclasses of Shape will be able to be drawn to the screen.

public abstract class Shape
{
	private Point location;
 
	public Shape( Point center)
	{
		location = center;
	}
 
	public Point getLocation()
	{
		return location;
	}
 
	public abstract void draw();
}
Now if we want to create different types of shapes such as squares or triangles we need to extend the Shape class and define the draw method differently for each type of Shape. We cannot extend the Shape class without defining draw within the subclass.

The syntax for writing a class definition that extends an abstract class is no different from the syntax used to extend a non-abstract class. You only need to ensure that within the subclass you include the implementation for all abstract methods of the abstract class.

Interfaces

An Interface is similar to a class in that it consists of method headers and constant definitions. Unlike a class, however, an interface contains no executable code. An interface is used to define behaviours that implementing classes must support. You don't care how the interface is actually implemented but certain methods have to be present. An interface is similar to an abstract class that has no state and in which every method is abstract.

Interfaces differ from abstract classes in that they do not allow class variables to be defined. In an interface, all methods are public and only constants which are defined both static and final are permitted. Interfaces also do not allow constructors, since an interface can never be instantiated.

To define an interface we replace class in the class definition with the keyword interface. To better illustrate how to define an interface we will look at the Shape class above converted into an interface:

public interface Shape 
{
	public Point getLocation();
 
	public void draw();
 
	public float getArea();
}

As you can see we have removed all class variables as well as all implementation of the methods. We have also added the function getArea. If we wish to implement an interface we must replace the keyword extends as used in regular inheritance with implements. We also must make sure we implement all methods that are described in the interface.

Interfaces are used when we wish to create a specification for a subclass that must have certain functions defined in order for it to be used correctly by other classes in the system. Interfaces can be thought of as a template for creating proper subclasses. For instance, if our Shape class was to be used by a larger drawing program it would be beneficial for us to implement Shape as an interface. If we have a Circle class that implements Shape, we can be sure that all the functions outlined in the Shape interface will be present in the Circle class and thus no errors will occur when the drawing program tries to call one of Shape's functions within Circle. For example, a circle's area is defined differently than a square's or rectangle's area so we can ensure that this function is implemented correctly by each individual shape by creating Shape as an interface and adding the function getArea to it. This will allow the drawing program to call getArea on any Shape subclass. If there is any common functionality for all Shape objects that would be implemented in exactly the same way for all Shape objects (like getLocation above), then it makes sense to make Shape an abstract class that implements the common functionality instead of making it an interface.

One big difference between interfaces and regular classes is that you can implement several interfaces within one class while you cannot inherit from multiple superclasses. The reason behind this is that if we have two methods with the same signature in two different interfaces there is no confusion between which implementation to use, as only a single implementation exists. Since interfaces do not have any implementation for any of their methods, one class can define the same method for both. If we try to inherit from two different classes that have a method with the same signature it is impossible to determine which implementation is the correct one to use. With multiple sources, inheritance creates confusion over which implementation of identical methods to use. This is why Java does not allow multiple inheritance. So if you need to be able to have classes implement more than a single interface, then it makes sense to create interfaces instead of abstract classes, as only a single abstract class can be extended by any class.


Patrice Belleville
Last modified: Thu Jan 27 2005 by PC