Home
8Overriding, Polymorphism & Abstract Classes
8

Topic 8 of 13 · Lectures 11–12

Overriding, Polymorphism & Abstract Classes

Replacing inherited behaviour with method overriding, dynamic method dispatch, casting within a hierarchy, abstract classes, final classes and methods, and using library classes.

← → move between slides · F full screen · M slide list

Before we start

Why this matters

One loop, one line — for (Shape s : shapes) total += s.area(); — correctly adds the areas of circles, rectangles and triangles. How does one line know three formulas?

Each object carries its real class with it. When the program runs, Java looks at the object, not the variable, to decide which area() to call. That is dynamic method dispatch, the engine behind polymorphism.

Abstract classes then let you say “every Shape has an area” without pretending to know a formula for a shape in general.

Outline · Lectures 11–12

Topics in this chapter

Select a topic to jump to the slide that explains it.

  1. Method overriding
  2. Dynamic method dispatch
  3. Abstract classes
  4. final with classes and methods
  5. Using library classes

Concept 1 of 5

Method overriding

class Animal {
    String sound() { return "..."; }
}
class Dog extends Animal {
    @Override
    String sound() { return "Woof"; }
}
class Cat extends Animal {
    @Override
    public String sound() { return "Meow"; }  // wider access OK
}
  • A subclass overrides a method by declaring the same name, parameters and a compatible return type.
  • Access may be the same or wider, never narrower (protected → public is OK).
  • @Override asks the compiler to check that you really are overriding — a typo like sound(int x) becomes an error instead of a silent overload.
  • static, private and final methods cannot be overridden.

Concept 2 of 5

Overloading vs overriding

OverloadingOverriding
WhereSame class (or subclass)Subclass of the declaring class
ParametersMust differMust be the same
Return typeCan be anythingSame or a subtype (covariant)
ChosenAt compile time from argument typesAt run time from the object’s class
PurposeConvenience: several ways to callSpecialise inherited behaviour
Also calledStatic (compile-time) polymorphismDynamic (run-time) polymorphism

Concept 3 of 5

Dynamic method dispatch

Dog and Cat both override sound().

Dynamic method dispatch

Animal a;             // reference type: Animal
a = new Dog();
System.out.println(a.sound());   // Woof
a = new Cat();
System.out.println(a.sound());   // Meow
// a.fetch();   ✗ compile error: Animal has no fetch()
  • A superclass reference can refer to any subclass object (upcasting is automatic).
  • Compile time: the reference type decides which methods you may call.
  • Run time: the object’s actual class decides which version runs.

Interactive

Dynamic dispatch explorer

Interactive

Downcasting and instanceof

Concept 4 of 5

Abstract classes

Shape is abstract (italic name): it declares area() but leaves the formula to subclasses.

Abstract classes

abstract class Shape {
    protected String name;
    Shape(String name) { this.name = name; }
    abstract double area();              // no body
    String describe() {                  // concrete method
        return name + " with area " + area();
    }
}
class Circle extends Shape {
    private double r;
    Circle(double r) { super("Circle"); this.r = r; }
    double area() { return Math.PI * r * r; }
}
  • An abstract method has no body; an abstract class cannot be instantiated: new Shape() ✗.
  • A subclass must implement every abstract method — or be abstract itself.
  • Abstract classes can still have fields, constructors and concrete methods.

Step through the code

Trace: polymorphic area()

One array, three objects, one call. Watch which area() frame appears for each element.

Step through the code

Trace: polymorphic area() (cont.)

Interactive

Polymorphic shapes

Concept 5 of 5

final classes and methods

class Account {
    final void audit() { /* must not change */ }
}
class Savings extends Account {
    void audit() { }   // ✗ cannot override final method
}

final class Money { }
class Taka extends Money { }   // ✗ cannot inherit from final
  • A final method keeps its behaviour in every subclass — useful for security checks and template steps.
  • A final class cannot be extended: String, Integer, Math.
  • abstract final is a contradiction and does not compile.
  • final calls can be bound early, which also lets the JIT inline them.

Code example

Using library classes

import java.util.*; ArrayList<String> names = new ArrayList<>(); names.add("Sadia"); names.add("Imran"); names.add("Mitu"); Collections.sort(names); System.out.println(names + " size=" + names.size()); Integer boxed = 42; // autoboxing int n = Integer.parseInt("123") + boxed; // wrapper helpers System.out.println(n + "" + Integer.toBinaryString(10)); System.out.println(Math.max(3, 8) + "" + Math.sqrt(49) + "" + Math.round(2.5)); Object o = names; // polymorphism again System.out.println(o instanceof List);
Output
[Imran, Mitu, Sadia] size=3
165 1010
8 7.0 3
true
  • The Java library (API) is thousands of ready-made classes. Read their documentation for constructors, methods and exceptions.
  • Wrapper classes (Integer, Double, …) let primitives be used as objects in collections.

Worked example 1 of 3

Worked example 1

What is printed?
class A { void f() { System.out.print("A"); } }
class B extends A { void f() { System.out.print("B"); } }
A x = new B(); x.f(); ((A) x).f();
Show the solution
BB. Casting the reference does not change the object; dispatch still picks B.f().

Worked example 2 of 3

Worked example 2

Given Animal a = new Dog();, what happens with (1) Dog d = a; (2) Dog d = (Dog) a; (3) Cat c = (Cat) a;?
Show the solution
  1. Does not compile: an Animal is not necessarily a Dog.
  2. Compiles and works.
  3. Compiles, but throws ClassCastException at run time because the object is a Dog.

Worked example 3 of 3

Worked example 3

Design an abstract Employee with abstract earnings() and two concrete subclasses.
Show the solution
abstract class Employee {
    protected String name;
    Employee(String name) { this.name = name; }
    abstract double earnings();
}
class Salaried extends Employee {
    private double monthly;
    Salaried(String n, double m) { super(n); monthly = m; }
    double earnings() { return monthly; }
}
class Hourly extends Employee {
    private double rate; private int hours;
    Hourly(String n, double r, int h) { super(n); rate = r; hours = h; }
    double earnings() { return rate * hours; }
}

Practice

Practice (1 of 2)

Try each one on paper first, then check your answer.

1. State three rules a method must follow to override another.
Show the answer
Same name and parameter list; return type the same or a subtype; access not more restrictive; cannot throw broader checked exceptions; the original must not be final, static or private.
2. Can an abstract class have a constructor? Why?
Show the answer
Yes. It runs when a subclass object is created (via super(...)) to initialise the abstract class’s fields.
3. What is printed? Shape s = new Circle(1); System.out.println(s instanceof Shape);
Show the answer
true — a Circle is a Shape.

Practice

Practice (2 of 2)

Try each one on paper first, then check your answer.

4. Why is String declared final?
Show the answer
So no subclass can change its behaviour (for example make it mutable), which keeps strings safe to share, cache and use as keys.
5. Write a loop that calls speak() only on the Dogs in an Animal[].
Show the answer
for (Animal a : zoo)
    if (a instanceof Dog d)   // Java 16 pattern
        d.speak();
6. Is overloading resolved at compile time or run time? Overriding?
Show the answer
Overloading at compile time (static binding); overriding at run time (dynamic binding).

Check yourself

Quiz

Summary

Summary

  • Overriding redefines an inherited method with the same signature; @Override lets the compiler check it.
  • The reference type limits which methods you may call; the object’s class decides which version runs.
  • Downcasting needs an explicit cast and is checked at run time; use instanceof to test first.
  • Abstract classes cannot be instantiated and may declare abstract methods that subclasses must implement.
  • final methods cannot be overridden; final classes cannot be extended.