Goals

  • Inheritance
    • How / Why / When to extend a class
    • What's in a subclass
    • Using Super
  • Using Subclasses
    • Polymorphism
    • Overriding

Resources

http://processing.org/learning/basics/inheritance.html
http://processing.org/learning/topics/multipleparticlesystems.html

"The most perfect political community is one in which the middle class is in control, and outnumbers both of the other classes." ~ Aristotle

How to Extend a Class

Extending a class is simple. In a new class definition, simply add the word extends and the name of the class the new class should extend. This new class is now a subclass of the class which it extends.

Why Extend a Class

In processing and other programming languages there are various tools to help add complexity to a program without requiring the programmer to rewrite a lot of code. In fact, good programming practice should have you never writing the same code twice. Since we are working with objects, sometimes it's beneficial to describe objects as more specific versions of some general object.

Take a look at these bikes. There is a general Bicycle object, and then there are a few specific Bicycle objects. Each specific Bicycle object extends the general Bicycle class, and therefore is a subclass of the Bicycle class.

When to Extend a Class (Abstraction)

As mentioned previously, the goal of efficient programming is to never repeat yourself. If we find that when creating a new object we're repeating a lot of the fields and methods that belong to another, similar object. We might want to "abstract" out the common properties of both classes, and put these into a parent class. Now each object from before can inherit these common fields and methods, and there's no need to code them for each object.

Take another look at the bikes. Every bicycle needs a position, wheel rotation, gear, etc...
But only a mountain bike would need shock suspension. And perhaps only a race bike would need road tires, or a spedometer.
When designing several classes, always remember that common fields and methods should be combined into a parent class, and each class should extend from that parent. This will save time and create cleaner, more flexible code.

Use the extends keyword when declaring a class to make it a subclass of another.
Use inheritence when several classes are sharing common fields and methods.

Subclasses

A subclass is simply a class which extends another class. This is called inheritance because the sublclass inherits the fields and methods of the parent class. Let's take a look at the anatomy of a subclass:

Notice how our subclass RaceBike inherits the fields and methods of Bicycle? This means that each new RaceBike object can set the values of xPos, yPos, xVel, yVel, in addition to the new field spedometer (specific to the RaceBike class).

Let's take a look at how we could create an instance of the RaceBike class and use some inherited fields and methods from the Bicycle class:

Super

Super is a special scoped reference variable which can be used to the set the scope to the parent class. Scope is what is visible or accessible by processing. This means we can use super to transition from the scope of our subclass to the scope of the parent class. Let's take a look at how we can use super:

The super( ... ) Constructor

Sometimes it may be advantageous for a subclass to call the constructor of it's parent class. We can achieve this by using the super( ... ) constructor. Here's an example:

Notice when using super( ... ) we must pass in parameters to match the constructor we are calling. There are two constructors here: one to initialize the bike with a random position, and the other (overloaded) one to initialize it with a specific position. By using super( ... ) with appropriate arguments for each constructor in the subclass RaceBike, we've managed to match parameters and leverage the code that was already written in the Bicycle class constructors.

The super Reference Variable

We can also use super as a special reference variable to call methods of a parent class from within the subclass. Here's an example:

A subclass inherits all fields and methods of the parent class, except the constructor.
Each class must have a unique constructor, however we can use the super() method to call the parent class constructor.
We can also call methods of the parent class using super as a special reference variable, referring to the parent class and all of it's methods.
When we use super() in any way, we must make sure that we are calling the constructors and methods with the correct arguments as specified by the parameters of those methods.

Polymorphism

Remember how a subclass inherits all of the fields and methods of a parent class? This means that processing now considers the subclass to be an equivalent of the parent class. This principle is called polymorphism and we usually say that an instance of a subclass "is a" instance of the parent class.
In other words: a RaceBike "is a" Bicycle.
Let's see this in action:

Storing a subclass reference using the parent class type is totally legal, however the reverse is not possible. Since a RaceBike "is a" Bicycle, we can use a Bicycle reference variable to store a RaceBike reference, but a Bicycle is not necessarily a RaceBike.

Advantages

Polymorphism has it's advantages, since all Bicycle subclasses can be treated as if they were Bicycles. For instance we can take all Bicycle instances, regardless of type, and store them in a single typed ArrayList since they are all Bicycles.

Disadvantages

There is a disadvantage to using the parent type to store a reference of a subclass. The reference variable type is of the parent class, therefore we cannot use this variable to access the fields or methods of the subclass. Let's see an example:

Overriding

Overriding is similar to overloading, however it involves a subclass implementing a method with the exact same method signature as the parent class. If an instance of the subclass is stored in a reference variable of the parent type, the overridden methods of the subclass will be called instead of the parent's methods. By overriding methods properly we can treat all objects as the parent type, call the same methods, while having different implementations. Here is an example:

Notice how the RaceBike methods have the same method signature as the Bicycle methods. Even if a RaceBike is stored in a reference variable of type Bicycle, when we call the methods of this variable we will in fact be calling the overridden methods from the RaceBike class.

A class which extends another has an "is a" relationship with it's parent class.
When an instance of a subclass is stored in a reference variable of the parent class type, only the fields and methods belonging to the parent class are visible.
Overriding allows us to call methods of the subclass even when using reference variables of the parent class type.