Niklas S
Niklas S

Reputation: 1

Java class inheritance how does the compiler know which method needs to be used

Can someone explain how does the compiler works out which method he should take

class All { /* ... */ }
class Most extends All { /* ... */ }
class Special extends Most { /* ... */ }

class Top {
    public void m( All p ) { System.out.print("A "); }
}

class Middle extends Top {
    public void m( All p ) { System.out.print("M "); }
    public void m( Special p ) { System.out.print("L "); }
}

class Bottom extends Middle {
    public void m( Most p ) { System.out.print("V "); }
    public void m( Special p ) { System.out.print("X "); }
}

class Test {
    public static void run() {

        All all = new All();
        Most most = new Most();
        Special special = new Special();
    
        Top x = new Middle();
        Top y = new Bottom();
        Middle z = new Bottom();
    
        x.m( most );
        x.m( special );
        y.m( all );
        y.m( special );
        z.m( all );
        z.m( most );
    }
}

For example you see a class inheritance of top, middle and bottom and all, most and special in this code. If I run this I get the output of M M M M M M.

I need to know why the compiler always takes the method m() of the middle class.

Why x.M(special) doesn't print out L?
Why does y.M(all) and y.M(special) print out M again?

Upvotes: 0

Views: 93

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1499860

There are two aspects involved here:

  • Overloading, which occurs at compile-time, and which selects the appropriate method signature based on the compile-time method target and arguments
  • Overriding, which occurs at execution-time, and which selects the implementation of the method (with the compile-time-selected signature) based on the execution-time type of the object.

In your specific example, x.m(special) needs to resolve a call with a target type of Top (the compile-time type of x) and an argument of Special (the compile-time type of special).

There's only one method called m in Top, and that's m(All), so that's what the compiler selects (after validating that there's an implicit conversion from Special to All). At execution time, the type of the object that x refers to is Middle, so it executes the implementation of m(All) in Middle. Likewise the compile-time type of y is Top, so the m(All) signature is picked, and it doesn't matter that y is actually an instance of Bottom, because Bottom doesn't override m(All).

Upvotes: 6

Related Questions