Java Intermediate: Objects, Collections and Errors
Inheritance and Interfaces
In this lesson you will
- Extend a class and override its methods
- Use abstract classes and interfaces
- Explain polymorphism
Introduction
Many things in the real world are specialised versions of something more general: a Cat and a Dog are both Animals. Inheritance lets one class build on another, reusing its code and adding its own. Interfaces describe abilities that unrelated classes can share. Together they are the basis of flexible Java design.
Extending a class
extends makes a subclass that inherits the fields and methods of its superclass.
Java
class Animal {
protected String name;
Animal(String name) {
this.name = name;
}
void eat() {
System.out.println(name + " is eating");
}
String sound() {
return "some sound";
}
}
class Dog extends Animal {
Dog(String name) {
super(name);
}
@Override
String sound() {
return "woof";
}
void fetch() {
System.out.println(name + " fetches the ball");
}
}
public class Main {
public static void main(String[] args) {
Dog rex = new Dog("Rex");
rex.eat();
System.out.println(rex.sound());
rex.fetch();
}
}Rex is eating
woof
Rex fetches the ballDoginheritsnameandeat()fromAnimal.super(name)calls the superclass constructor. It must be the first line of the subclass constructor.@Overridereplacessound()with the Dog's own version.protectedlets subclasses see the field.
Java allows a class to extend only one class.
Quick quiz
What does super(name) do in a subclass constructor?
Polymorphism
Because a Dog is an Animal, you can store it in an Animal variable. When you call a method, Java runs the version belonging to the actual object. One call, different behaviour: this is polymorphism.
Java
class Animal {
String sound() {
return "some sound";
}
}
class Dog extends Animal {
@Override
String sound() {
return "woof";
}
}
class Cat extends Animal {
@Override
String sound() {
return "meow";
}
}
public class Main {
public static void main(String[] args) {
Animal[] zoo = {new Dog(), new Cat(), new Animal()};
for (Animal a : zoo) {
System.out.println(a.sound());
}
}
}woof
meow
some soundThe loop only knows it has Animals. It does not need to know which kind, and you can add a new subclass without changing the loop at all.
Abstract classes
Sometimes the parent is too general to exist on its own. A "Shape" has no area until we know which shape. An abstract class cannot be instantiated, and may declare abstract methods that every subclass must provide.
Java
abstract class Shape {
abstract double area();
void describe() {
System.out.println(getClass().getSimpleName() + " with area " + area());
}
}
class Circle extends Shape {
private final double radius;
Circle(double radius) {
this.radius = radius;
}
@Override
double area() {
return Math.round(Math.PI * radius * radius * 100) / 100.0;
}
}
class Rectangle extends Shape {
private final double width;
private final double height;
Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
double area() {
return width * height;
}
}
public class Main {
public static void main(String[] args) {
Shape[] shapes = {new Circle(1), new Rectangle(3, 4)};
for (Shape s : shapes) {
s.describe();
}
}
}Circle with area 3.14
Rectangle with area 12.0new Shape() would be a compile error. The shared describe() method is written once and works for every shape.
Interfaces
An interface is a pure contract: a list of methods a class promises to provide, with no fields of its own. A class implements an interface, and it can implement many.
Java
interface Flyer {
void fly();
}
interface Swimmer {
void swim();
}
class Duck implements Flyer, Swimmer {
@Override
public void fly() {
System.out.println("Duck flaps into the air");
}
@Override
public void swim() {
System.out.println("Duck paddles");
}
}
class Plane implements Flyer {
@Override
public void fly() {
System.out.println("Plane takes off");
}
}
public class Main {
static void launch(Flyer f) {
f.fly();
}
public static void main(String[] args) {
launch(new Duck());
launch(new Plane());
}
}Duck flaps into the air
Plane takes offA Duck and a Plane are unrelated, but both can fly, and launch works with anything that does. Interface methods are public automatically, so implementations must be public.
Since Java 8, interfaces can also provide default methods with a body:
Java
interface Greeter {
String name();
default String greet() {
return "Hello, " + name() + "!";
}
}
class Person implements Greeter {
@Override
public String name() {
return "Asha";
}
}
public class Main {
public static void main(String[] args) {
System.out.println(new Person().greet());
}
}Hello, Asha!Quick quiz
How many classes can a Java class extend, and how many interfaces can it implement?
Abstract class or interface?
- Use an interface to describe what something can do (Flyer, Comparable, Runnable). A class can have many.
- Use an abstract class when related classes share state and code (a common name field, a shared helper).
- When unsure, start with an interface. It is more flexible.
A built-in example: Comparable
The standard library uses interfaces everywhere. If a class implements Comparable, Java can sort it:
Java
import java.util.Arrays;
class Student implements Comparable<Student> {
private final String name;
private final int grade;
Student(String name, int grade) {
this.name = name;
this.grade = grade;
}
@Override
public int compareTo(Student other) {
return Integer.compare(grade, other.grade);
}
@Override
public String toString() {
return name + "(" + grade + ")";
}
}
public class Main {
public static void main(String[] args) {
Student[] students = {
new Student("Asha", 85),
new Student("Ben", 72),
new Student("Chloe", 91)
};
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
}[Ben(72), Asha(85), Chloe(91)]Try it yourself
On your computer, create an interface Payable with a method double pay(). Make two classes, Employee (fixed monthly salary) and Contractor (hourly rate times hours), that implement it. Put both in an array of Payable and print the total pay.
Summary
extendscreates a subclass that inherits and can override (@Override) methods.super(...)calls the parent constructor.- Polymorphism: a call runs the method of the actual object, so one loop can handle many kinds.
- An abstract class cannot be created and can require methods. A class implements any number of interfaces.
- Use interfaces for abilities and abstract classes for shared code.
Lesson complete
+20 XP
Nice work. Keep going while it is fresh.