Simple Inheritance Tutorial

This tutorial demonstrates the basics of class inheritance in Java. There are three classes in three files that are used by the main method of BasicClass to demonstrate how inheritance works. BasicClass overrides the toString() method of Object, which is overriden by each of its descendants (NumberedClass and LetteredClass).

Each of the three classes also provide a method that cannot be overridden or inherited by other classes, because it is marked final. Of note is that even when a descendant is referenced as or cast to its ancestor class, the overridden methods will also be invoked, and not the originals in the ancestor.

BasicClass.java

package edu.rutgers.sakai.java.inheritance;

/**
 * A very simple class to be extended by other classes.
 * 
 * @author Robert Moore
 */
public class BasicClass {

	/**
	 * A unique value for this object.
	 */
	protected Object value;
	
	public BasicClass(Object value){
		this.value = value;
	}
	
	/**
	 * Overrides {@code Object#toString()} and returns the string "Basic (?)"
	 * instead, where ? is the String representation of this object's value.
	 */
	@Override
	public String toString() {
		return "Basic (" + this.value.toString() + ")";
	}

	/**
	 * Returns a string that is unique to {@code BasicClass}. This method cannot
	 * be overridden by descendants because it is a {@code final} method.
	 * 
	 * @return the string "Unique to Basic".
	 */
	public final String basicOnly() {
		return "Unique to Basic";
	}

	/**
	 * A main method for demonstrating inheritance using the
	 * {@code LetteredClass} and {@code NumberedClass} classes as well as
	 * {@code BasicClass}.
	 * 
	 * @param args
	 *            ignored.
	 */
	public static void main(String[] args) {
		BasicClass basic = new BasicClass(Float.valueOf(1.4f));

		NumberedClass numbered = new NumberedClass(Integer.valueOf(5));

		LetteredClass lettered = new LetteredClass(Character.valueOf('F'));

		// We can assign an object to a reference of any of its ancestors, but
		// we will only
		// have access to the ancestor methods.
		BasicClass letteredBasic = lettered;

		BasicClass numberedBasic = numbered;

		// When we concatenate an object with a String, it automatically calls
		// toString() on the object
		System.out.println("B: " + basic.toString());
		System.out.println("B: " + basic.basicOnly());

		System.out.println();

		// The next 3 lines will print out the NumberedClass.toString() value
		System.out.println("N: " + numbered.toString());
		System.out.println("NB: " + numberedBasic.toString());
		System.out.println("(B)N: " + ((BasicClass) numbered).toString());

		// The basicOnly() method always comes from the BasicClass, and cannot
		// be overridden
		System.out.println("N: " + numbered.basicOnly());
		System.out.println("NB: " + numberedBasic.basicOnly());

		// This method only exists in the descendant (NumberedClass), so cannot
		// be called either by numberedBasic or a cast to a BasicClass
		System.out.println("N: " + numbered.descendantOnly());

		System.out.println();

		// The next 3 lines will print out the NumberedClass.toString() value
		System.out.println("L: " + lettered.toString());
		System.out.println("LB: " + letteredBasic.toString());
		System.out.println("(B)L: " + ((BasicClass) lettered).toString());

		// The basicOnly() method always comes from the BasicClass, and cannot
		// be overridden
		System.out.println("L: " + lettered.basicOnly());
		System.out.println("LB: " + letteredBasic.basicOnly());

		// This method only exists in the descendant (LetteredClass), so cannot
		// be called either by letteredBasic or a cast to a BasicClass
		System.out.println("L: " + lettered.descendantOnly());

	}
}

NumberedClass.java

LetteredClass.java