-4

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?

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52

2 Answers2

2

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.

Rogue
  • 11,105
  • 5
  • 45
  • 71
0

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • That is how I understood it all those years, yet In my current app Super.m2 got called. But it is was because of the Sub.m2 having a private access level. I changed the access level to protected and all is working as expected now. – Jan Verrept Apr 24 '23 at 12:31
  • You have provided no code. I stand by my answer based on the question as posed. – matt Apr 24 '23 at 12:33
  • Your explanation is completely wrong: it's not "directed to the first m2 found when looking up", lol. It's due to `override` modifier. – timbre timbre Apr 24 '23 at 14:06
  • @klangfarb We don't agree, that's fine. – matt Apr 24 '23 at 14:20
  • @klangfarb the `@Override` annotation is syntactic sugar: it won't change any runtime behavior. The only behavior it does introduce is a compiler error if you add it to a non-overridden method. It does "walk the inheritance chain", but that can be sightly more nuanced than I care to phone-type in a tiny comment – Rogue Apr 24 '23 at 14:39
  • @JanVerrept you can always make an overridden method more visible, but never less visible. – Rogue Apr 24 '23 at 14:43
  • @Rogue in Swift `override` is NOT a syntactic sugar. And what you state is probably relevant for the language you used in your answer. For Swift, it's not. – timbre timbre Apr 24 '23 at 15:15
  • @Rogue actually thinking on it further: it may be that language you are talking about defaults to overriding, but there are still 2 completely different things conceptually on any language: "override the function" and "define the function withe the same name/arguments". They are not the same thing – timbre timbre Apr 24 '23 at 15:26
  • I was speaking to Java, yes (admittedly confusing since OP's original tags were Java and Swift). Java does override a matching, as-open-or-more visibility method signature by default – Rogue Apr 24 '23 at 15:59