Java 5: Inheritance

From Deep Blue Robotics Wiki
Jump to: navigation, search

Inheritance is another key feature of the Java language. It allows a class to inherit code from another class that has most of the same functionality. In this section, you will learn how to use inheritance in your own programming.

Subclasses

The simplest form of inheritance is a subclass inheriting code from a superclass. To create a subclass of another class (called the superclass), use the keyword extends in the subclass declaration:

public class MySubclass extends MySuperclass

A subclass inherits all of the code from its superclass, so any methods or variables that the superclass possesses will be possessed by the subclass as well. A subclass can also have methods and fields of its own, but these will not be shared with the superclass. Here is an example using a Dog class that extends an Animal class:

public class Animal {
  boolean hungry = true;
  public void eat() {
      hungry = false;
  }
}
public class Dog extends Animal {
  public void bark() {
      System.out.println("Woof");
  }
}

In this example, the Dog class possesses both the bark method and the eat methods, even though the eat method was only defined in the Animal class. Additionally, the hungry variable in the Animal class is available to code the Dog class as though it had been defined in the Dog class itself.

An instance of a subclass can be used in place of an instance of its superclass. For example, this code would be completely legal:

Animal animal = new Dog();
animal.eat();

However, the compiler does not know that the animal variable is actually an instance of the Dog class, so this code would cause an error:

Animal animal = new Dog();
animal.bark();

Overriding

Sometimes, you might want to change code that was inherited from a superclass. The way to do this is to override the method that you want to change. To override a method, create a method in the subclass with the exact same name, parameters, and return type. This method will always be called in place of the superclass version of the method. In this example, the Dog class overrides the getName method of the animal class:

public class Animal {
  public String getName(){
      return "Animal";}
}
public class Dog extends Animal {
  public String getName() {
      return "Dog";
  }
}

Now, if the getName method is called on an instance of Dog, it will always return "Dog" even if that instance is stored in an Animal variable:

Dog dog = new Dog();
Animal animal = new Dog();
System.out.println(dog.getName()); // This will print "Dog"
System.out.println(animal.getName()); // This will also print "Dog"

Unlike methods, however, constructors are not inherited from a superclass, so they must be redefined in the subclass. In this example, the Dog constructor will replace the constructor in the Animal class:

public class Animal {

  int numberOfLegs;
  public Animal(int numberOfLegs) {
    this.numberOfLegs = numberOfLegs;
  }
}
public class Dog extends Animal {
  public Dog() {
    numberOfLegs = 4;
  }
}

Super

There is a way to specifically access the methods of the superclass, using the keyword super. It is similar to the keyword this, except it will always refer to the superclass version of a method. In this example, the Dog class will call both the bark method and the superclass eat method whenever eat is called:

public class Animal {

    boolean hungry = true;
    public void eat() {
        hungry = false;
    }
}
public class Dog extends Animal {
    public void bark() {
        System.out.println("Woof");
    }
    public void eat() {
        super.eat();
        bark();
    }
}

Note that if the call to super.eat() was replaced by a call to eat() without the super, the method would call the subclass version of eat instead, leading to an infinite recursive loop.

The super keyword can also be used to call a superclass constructor. Simply type the keyword super, followed by the constructor parameters in parenthesis:

public class Animal {

    int numberOfLegs;

    public Animal(int numberOfLegs) {
        this.numberOfLegs = numberOfLegs;
    }
}

public class Dog extends Animal {
    public Dog() {
        super(4);
    }
}

Note that super must be the first statement in a constructor if it is used (so you can't call 2 different constructors). Additionally the superclass no-arguments (no-args) constructor will automatically be called at the beginning of the subclass constructor if no call to a super constructor is used. This can cause an error if the superclass has a constructor with arguments but not one without arguments, because the subclass will try to call a no-args constructor that doesn't exist.

Interfaces

An interface is a collection of methods that any class using the interface is required to implement on its own. Interfaces are declared the same way as classes, except with the keyword interface instead of class. They can also extend any number of other interfaces, separated by commas:

public interface Interface { }
public interface Interface extends Interface1, Interface2 { }

Methods declared in interfaces have no implementation of their own, so instead of a method body, they end with a semicolon. They are always public, so the public modifier is not necessary.

void doSomething(int a, int b);

A class can implement an interface using the implements keyword, just like the extends keyword is used for a superclass. While a class may only extend one superclass, it can implement any number of interfaces. If a class has both a superclass and an interface, the two declarations are combined:

public class Class1 implements Interface { }
public class Class2 implements Interface1, Interface2, Interface3 { }
public class Class3 extends Superclass implements Interface { }

To implement an interface, a class must also contain all of the methods that the interface declares:

public interface Interface {
    void doSomething();
}

public class Class implements Interface{
    public void doSomething() {
        System.out.println("Hello, world.");
    }
}

Like with a superclass, any class that implements an interface can be treated as if it were an instance of that interface (although you cannot actually instantiate an interface):

Interface interface = new Class();
interface.doSomething();

An interface cannot have instance variables, but it can declare constants. Any constants declared within an interface will automatically be public, static, and final, so they can be declared without any additional modifiers. Constant names are traditionally completely capitalized:

public interface MyInterface {
    double PI = 3.14159;
}

An interface can also define static methods, which the subclass doesn't need to implement. These methods are automatically considered public.

public interface MyInterface {
    static void doSomethingElse {
        System.out.println("Hi");
    }
}

Inheritance Modifiers

There are some modifiers that are used specifically for inheritance, as well as some new uses for old modifiers.

Abstract - An abstract class is a class that cannot be instantiated, only subclassed. Abstract classes can have abstract methods, which are methods with no implementation. Subclasses must implement these methods (just like classes which implement an interface must provide implementations of the methods in the interface). Abstract methods cannot be private (otherwise they could never be overridden).

Default - Interfaces can have default methods, which have their own implementation. Classes that extend the interface can choose whether or not to override the method. Default methods are public automatically.

Final - When applied to a class, the final modifier indicates that the class cannot be subclassed. Final methods cannot be overridden.

Access Modifiers - When overriding a method, the new version of the method must have at least as much access as the method it is overriding. For example, a protected method could be overridden by a public or protected method, but not by a private method.


Next Lesson: Design Principles