Overriding methods in Java classes

Java inheritance - methods overriding

We’ve seen some cool examples that should show us how the inheritance in Java actually works. They included following examples

import static java.lang.System.out;

class A {
    void a() { out.println("A::a"); }

    void b() { out.println("A::b"); }

    Object c() { return "A::c"; }

    static void z() { out.println("static A::z"); }

    static void y() { out.println("static A::y"); }

class B extends A {
    @Override void a() { out.println("B::a"); }     // @Override not required (extra check by compiler)

    @Override String c() { return "B::c"; }     // signature change but matches parent

    static void z() { out.println("static B::z"); } // cannot override static methods

    void d() { out.println("B::d"); }

public class Main {
    public static void main(String[] args) {
        final A aAsA = new A();
        final B bAsB = new B();
        final A bAsA = new B();

        aAsA.a(); // A::a
        bAsB.a(); // B::a
        bAsA.a(); // B::a

        aAsA.b(); // A::b
        bAsB.b(); // A::b
        bAsA.b(); // A::b

        bAsB.d(); // B::d
        // bAsA.d(); // don't compile

        A.z();      // static A::z
        B.z();      // static B::z
        aAsA.z();   // static A::z based on aAsA compile-time type
        bAsB.z();   // static B::z based on bAsB compile-time type
        bAsA.z();   // static A::z based on bAsA compile-time type

        A.y();      // static A::y
        B.y();      // static A::y
        aAsA.y();   // static A::y based on aAsA compile-time type
        bAsB.y();   // static A::y based on bAsB compile-time type
        bAsA.y();   // static A::y based on bAsA compile-time type

        out.println(aAsA.c());  // A::c
        out.println(bAsB.c());  // B::c
        out.println(bAsA.c());  // B::c

The main rules that you can follow when reasoning about such examples:

  • for class methods we look at the actual type of the object
  • for static functions we look at the type of the caller
  • to call the method it must be available in compile-time type of variable (so e.g. bAsA.d(); won’t compile as during compilation it’s considered to be of type A which doesn’t have d method)
  • methods from subclass can override methods making their types more detailed (as in case of c method)

Extra task

You can find extra task from today’s exercises here.