The features that make a programming language truly “Object-Oriented” are usually considered to be inheritance and polymorphism.

Here we’ll examine the concepts. 

What is Inheritance?

Why is Inheritance important?

Have you ever written some code, and then later found that you needed to write something that was almost, but not quite, the same?

What did you do?

  • Cut and paste the code, and then change it to suit? (Yeah, I know…)
  • Modify the existing code so it could handle both cases?
  • Why isn’t either of those solutions a good idea?

Inheritance provides a mechanism to allow you to extend existing code in a natural way.

Classifications, Taxonomies, and Inheritance

Humans are always classifying things!

Classification is a way of extracting out the common attributes of several like objects, and leaving only the differences.

Classification enables us to deal with new things in terms of what is already familiar to us; reduces volume of information; helps simplify.

We often call such classifications taxonomies. Taxonomies are everywhere.

For example:

Here are some more:

Inheritance

Inheritance is an abstraction mechanism which allows classes to be related hierarchically.

  • Allows classes to share definitions
  • Makes commonality of code explicit.

For example, consider the problem of drawing different kinds of graphical shapes. We can extract the common attributes and behaviors of any kind of shape, and encapsulate it in a Shape class:

The Circle, Triangle and Square classes inherit (or derive) their behaviors and properties from class Shape.

Inheritance vs. Containment

Containment (Aggregation)

A class can contain another class (a has-a relationship):

// Wheel.java
public class Wheel
{
    /* Details... */
}
// Car.java
public class Car
{
    public final int WHEEL_COUNT = 4;

    // Constructor
    public Car(String make, int maxSpeed)
    { 
	m_make = make; m_maxSpeed = maxSpeed; 
	m_wheels = new Wheel[WHEEL_COUNT];
	for (int i = 0; i < WHEEL_COUNT; i++)
	    m_wheels[i] = new Wheel();
    }

    // Data
    private String m_make;
    private int m_maxSpeed;
    private Wheel m_wheels[]; // a Car has wheels
}

Inheritance

…or a class can inherit from another class (an is-a or is-a-kind-of relationship):

// WheeledVehicle.java
public class WheeledVehicle
{
    // Constructor
    public WheeledVehicle(int wheelCount)
    {
	m_wheelCount = wheelCount;
	m_wheels = new Wheel[wheelCount];
	for (int i = 0; i < wheelCount; i++)
	    m_wheels[i] = new Wheel();
    }

    // Data
    private int m_wheelCount;
    private Wheel m_wheels[]; 
	// a WheeledVehicle has wheels
}
// Truck.java
public class Truck extends WheeledVehicle
	// Truck is-a-kind-of WheeledVehicle
{
    // Constructor
    public Truck(String make, int maxSpeed)
    { 
	super(WHEEL_COUNT);
	m_make = make; m_maxSpeed = maxSpeed; 
    }

    // Data
    private static int WHEEL_COUNT = 4;
    private String m_make;
    private int m_maxSpeed;
}

Whether to use inheritance or containment depends on what you’re trying to do:

Assuming that you are trying to decide whether a class B should inherit from a class A, or contain a class A, you should ask yourself:

“Is B a kind of A?”

If so, then use inheritance.

“Does B have an A?”

If so, then use containment.

Sometimes the answer is obvious:

“Is a Car a kind of Vehicle?”

“Does a Car have an Engine?”

and sometimes it’s not:

“Is a Point a kind of Location?”

“Does a Point have a Location?”