knowledge-kitchen

Object-Orientation - Inheritance & Polymorphism (in Java)

The problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.

Joe Armstrong, creator of Erlang, a functional programming language

  1. Overview
  2. Basic Implementation
  3. Multi-Level Inheritance
  4. Polymorphism
  5. Similarity & Difference
  6. Inheritance vs. Composition
  7. Is Inheritance Evil?
  8. Conclusions

Overview

Concept

Inheritance is a mechanism for basing one object or a class on another object or class when the two objects or classes include similar implementations of their behaviors.

Historical tangent

Inheritance was first implemented in Norway in 1969 for Simula, considered the first fully object-oriented programming language. Simula included now-standard, pedestrian, object-oriented features such as:

Think about that next time you hear someone say technology develops at lightning-speed rates of innovation.

Benefits

The touted benefits of inheritance include:

Basic Implementation

Abstract Example

Imagine we had the following class, A with just a single property, message, and its getter and setter methods.

public class A {
    // no-args constructor
    public A() {
        System.out.println( "A new A object is born!" );
        this.message = "Hello!";
    }

    // just one property to keep it simple
    private String message;

    // getter + setter methods
    public String getMessage() {
        return this.message;
    }
    public void setMessage(String message) {
        if (msg.length > 0) this.message = message;
    }
}

Abstract Example (continued)

Another class, B, could inherit the properties and methods of A by using the extends keyword.

public class B extends A {

}
B bObj = new B();
System.out.println( bObj.getMessage() );

Abstract Example (continued again)

We often create UML diagrams indicating class relationships, where the arrow points from parent to child.

Class inheritance UML diagram

Abstract Example (continued once more)

When this program is run, two lines are output:

A new A object is born!
Hello!
public B() {
        super();
}

Abstract Example (continued the final time)

The second line output above, ‘Hello!’, is a result of the call to the B object’s getMessage() method.

Visibility

By definition, the private property, message, of the A class is not visible from the B class.

Multi-Level Inheritance

Concept

We can continue our example by giving B its own child, C.

public class C extends B {

    // a no-args constructor
    public C() {
      super(); // call B's no-args constructor
    }

    // an overloaded constructor that accepts a message
    public C( String message) {
        super(); // call B's no-args constructor
        System.out.println( "A new C object is born!" );
        this.setMessage( message );
    }
}

Concept (continued)

A UML diagram showing multi-class inheritance.

Multi-class inheritance UML diagram

Analysis

C is now a child of B, which itself is a child of A.

C cObj = new C( "Welcome!!" );
System.out.println( cObj.getMessage() );

Try it!

Polymorphism

Concept

An object or class can assume more than one ‘shape’.

if (cObj instanceof C && cObj instanceof B && cObj instanceof A) {
    System.out.println("It's a C, B, and A object all-in-one!");
}

Application

Polymorphism can be useful when we want to store a bunch of related objects of different-but-related types into an array or other grouping data structure in order to perform some kind of batch operation on them.

A[] myObjs = {
    new A(),
    new B(),
    new C("Welcome!!")
};

for (A myObj : myObjs) {
    String message = myObj.getMessage();
    System.out.println(message);
}

Overriding

It is often desireable to have child classes implement the instance methods defined in the parent class somewhat differently.

super.getMessage();

Similarity & Difference

Concept

In real applications, child classes almost invariably do something different from their parent classes, whether by overriding some parent methods or implementing their own unique methods that are not present in the parent. This difference gives the child class a reaason to exist.

Example classes

The parent class:

public class A {
    public void doSomething() {
        System.out.println("An A object doing something.");
    }
}

The child class:

public class B extends A {
    public void doSomethingDifferent() {
        System.out.println("A B object doing something *different*.");
    }
}

Similarity

Since B inherits from A, both classes encapsulate A’s doSomething() method.

A myA = new A();
myA.doSomething();
B myB = new B();
myB.doSomething();

Similarity (continued)

Both A and B objects can be considered A objects, since B implements A’s public interface. So we can take advantage of polymorphism to perform a batch operation on both objects.

// instantiate an A and a B object
A myA = new A();
B myB = new B();
// put them both into an A-typed array
A[] myObjects = { myA, myB };
// loop through all objects in array
for (A myObj : myObjects) {
    myObj.doSomething(); // works fine, since they both have this method
}

Difference

B objects, of course, have their own unique doSomethingDifferent() method that A objects do not have.

// loop through all objects in array
for (A myObj : myObjects) {
    myObj.doSomething(); // works fine, since they both have this method from A

    // have any B-type objects do their special behavior...
    if (myObj instanceof B) {
        // first cast to B-type
        B sameObjsAsBType = (B) myObj;
        // now call B-type's unique method
        sameObjsAsBType.doSomethingDifferent();
    }
}

Inheritance vs. Composition

In context

The goals of inheritance are to reuse code, reduce redundancy, and provide conceptual clarity in code.

Example

For example, when using the Processing animation framework, the PApplet class contains lots of useful animation-related public properties and methods.

public class App extends PApplet { ... }
public class Donkey { ... }

Example (continued)

Our Donkey objects don’t need to pop open windows, draw ellipses, detect mouse clicks, key presses, or do the other things that the PApplet class can do. Our Donkey class represents donkeys, not app windows.

public class Donkey {
    private App app; // will hold an App object, which is our child class of PApplet

    public Donkey(App app) {
        this.app = app; //store the App object composed within this Donkey
    }

    public void drawMeToScreen() {
        this.app.image( ... ); // use the App object's image method to draw to screen
    }
    // ...

Example (continued again)

The App class can instantiate a Donkey object and pass itself to its constructor for the Donkey to hold a reference to.

public class App extends PApplet {

    private Donkey myDonkey; // will hold a Donkey object

    public void setup() {
        // pass this App object as an argument to the Donkey constructor
        this.myDonkey = new Donkey(this); // the Donkey will now have a reference to the App object
    }

    public void draw() {
        // the donkey can now draw itself to the screen
        this.myDonkey.drawMeToScreen();
    }
}

Criticisms of Inheritance

Concept

There are certainly those who criticise object-oriented progrmaming, and some specifically who disapprove of Java’s inheritance model.

Example scenario

Take, for example, the “Diamond-problem” scenario.

Example scenario (continued)

The following UML diagram shows our classes so far, with some example properties and methods.

Evil inheritance setup

Example scenario (continued again)

So far so good. But what if we added a Copier to the mix?

Evil inheritance problem

The problem

In Java, and many other languages, inheritance from multiple classes is impossible.

public class Copier {
    private Scanner scanner;
    private Printer printer;

    public Copier(Scanner scanner, Printer printer) {
        this.scanner = scanner;
        this.printer = printer;
    }
}

Conclusions

You have now extended your understanding of object-oriented programming to include class-based inheritance and polymorphism.