Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling super method from within super class

Tags:

java

As a brain-twister example a professor of mine gave us following exercise, to learn about inheritance. We had to figure out the output.

//java
public class A {
    public void f() {
        System.out.println("A -> f()");
        x = x + 4;
        if (x < 15) this.f(); //the f-call
    }
    public int x = 5;
}

public class B extends A {
    @Override
    public void f() {
        System.out.println("B -> f()");
        x = x + 3;
        super.f();
    }
}

public class Main {
    public static void
    main(String[] args) {
        A a = new B();

        System.out.println("a.f()");
        a.f();
        System.out.println(a.x);
    }
}

The output is, as I expected,

  • a.f()
  • B -> f()
  • A -> f()
  • B -> f()
  • A -> f()
  • 19

However, I was now wondering. Is there a way to make the f-call in A call the f method in A, even when I use it from an B-object, similar to the way I call the f from A in B using super.f(). So the output would become (I think):

  • a.f()
  • B -> f()
  • A -> f()
  • A -> f()
  • 16

Is this possible? And if so, how?

Note: I'm not sure what the practical application of this would be, I'm just trying to learn something new :P

like image 454
The Oddler Avatar asked Jan 21 '15 20:01

The Oddler


2 Answers

The short answer is "no" you cannot do this.

The longer answer is that allowing this would break all kinds of guarantees about inheritance. Your B class has essentially said "I now provide the canonical method for public void f()". Because B is providing said method it is allowed to call back in to the parent to use that (and something that's a very useful thing to do).

If A was allowed to do the same it would essentially be bypassing the behaviour that B wants to override.

There are a variety of patterns available that give you similar behaviour, e.g. the Template Pattern

like image 188
tddmonkey Avatar answered Oct 06 '22 08:10

tddmonkey


Because polymorphism will apply to all methods of a superclass object, the f that is called will be that of the object's runtime type always -- in this case, B, so B's f method will always be called. That cannot be changed in Java.

You may be able to work around this by doing the work of A's f method in a private method, say, foo, so that when f is called, foo is called repeatedly. In A:

public void f()
{
   foo();
}

private void foo() {
    System.out.println("A -> f()");  // Lie.
    x = x + 4;
    if (x < 15) this.foo(); //the "f"-call
}
like image 37
rgettman Avatar answered Oct 06 '22 09:10

rgettman