Search code examples
javaoopinheritancedynamic-dispatch

Dynamic dispatch and access level of a method


Consider the following classes:

public class A {
    public void foo() {
        System.out.println("A.foo()");
    }

    public void bar() {
        System.out.println("A.bar()");
        foo();
    }
}

public class B extends A {
    public void foo() {
        System.out.println("B.foo()");
    }

    public static void main(String[]
    args) {
        A a = new B();
        a.bar();
    }
}

The output of this code is A.bar() and then B.foo(). I've noticed that if I change the method foo()'s access level from public to private the output is: A.bar() and then A.foo().

Why?


Solution

  • If A.foo() is private, then it can't be overridden by a subclass - any other class should basically be unaware of the existence of private members. You can't override a member you can't "see".

    From section 8.4.8.1 of the JLS:

    An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true:

    • ...

    • One of the following is true:

      • mA is public.
      • mA is protected.
      • mA is declared with package access in the same package as C, and either C declares mC or mA is a member of the direct superclass of C.
      • mA is declared with package access and mC overrides mA from some superclass of C.
      • mA is declared with package access and mC overrides a method m' from C (m' distinct from mC and mA), such that m' overrides mA from some superclass of C.