OOP fundamentals: Mixing Superclass and subclass methods

130 views Asked by At

Using two classes,
a baseclass called Super and
a subclass called Sub
each have two instance-methods with the exact same names (called m1 and m2).

At runtime an instance of Sub is created and Sub.m1 is called
Sub.m1 first calls Super.m1 (and runs a few extra lines of code afterwards)
Super.m1 calls the second method "m2".

Knowing that the runtime instance was of class Sub to begin with,
which of the two implementations of m2 gets executed Super.m2 or Sub.m2?

2

There are 2 answers

9
matt On BEST ANSWER

A simple call to m2 (which is short for self.m2) will be directed to the first m2 found when looking up the inheritance chain from this instance — because that is what self means.

So if this instance is a Sub, then Sub's implementation of m2 is called if there is one, no matter where the calling method is located in the hierarchy.

0
Rogue On

To answer the direct question, it would call "Sub.m2". Here's a test case:

public class MyClass {
    public static void main(String args[]) {
        A test = new B();
        test.m1();
    }
    
    public static class A {
        
        void m1() { this.m2(); };
        void m2() { System.out.println("Hello from A!"); }
    }
    
    public static class B extends A {
        
        void m1() { super.m1(); }
        void m2() { System.out.println("Hello from B!"); } //this is printed
    }
}

Under the hood, the test variable is always (short of reassignment) an instance of B. The methods it inherits from A are welcome to call methods inside of A, but those methods in turn may be overridden by B as well. If B#m2 had a super call inside of it, you get even more information:

void m2() {
    System.out.println("Hello from B!");
    super.m2();
    System.out.println("Hello again from B!");
}

This gives us the result:

Hello from B!
Hello from A!
Hello again from B!

From this, we can see that the most-specific version of #m2 is called. In other words, since test is an instance of B, it calls B#m2 first. From there, B#m2 can decide to call superclass methods, or completely replace the old functionality. If B did not have an #m2 method, it would look to the parent classes of B for such a method next.