2

Please consider the following classes:

public interface BaseInterface {

    void method1();
    void method2();
    void method3();
}


public class BaseClass implements BaseInterface {

    @Override
    public void method1() {
        System.out.println("BaseClass.method1 IN");
        this.method3();
        System.out.println("BaseClass.method1 OUT");
    }

    @Override
    public void method2() {
        System.out.println("BaseClass.method2 IN");
        System.out.println("BaseClass.method2 OUT");
    }

    @Override
    public void method3() {
        System.out.println("BaseClass.method3 IN");
        System.out.println("BaseClass.method3 OUT");
    }
}


public class ChildClass extends BaseClass {

    @Override
    public void method1() {
        System.out.println("ChildClass.method1 IN");
        super.method1();
        System.out.println("ChildClass.method1 OUT");
    }

    @Override
    public void method2() {
        System.out.println("ChildClass.method2 IN");
        super.method2();
        System.out.println("ChildClass.method2 OUT");
    }

    @Override
    public void method3() {
        System.out.println("ChildClass.method3 IN");
        System.out.println("ChildClass.method3()");
        System.out.println("ChildClass.method3 OUT");
    }
}

In this case, if I create an instance of ChildClass:

BaseInterface cc1 = new ChildClass();

and then run method1 of this class

cc1.method1();

it will return the following output:

ChildClass.method1 IN
BaseClass.method1 IN
ChildClass.method3 IN
ChildClass.method3()
ChildClass.method3 OUT
BaseClass.method1 OUT
ChildClass.method1 OUT

So when I call this.method3() (or just method3()) from the super class (BaseClass), the method3 of the ChildClass is executed instead. I know this is the expected behavior but I just wonder how can I still call the BaseClass.method3 in this setup? Is this possible?

Please note that this is a purely theoretical question and I understand that in reality I probably should've instantiated a BaseClass instance in the first place. Is this the only way to get around that?

Eugene S
  • 6,709
  • 8
  • 57
  • 91
  • Here's an answer: https://stackoverflow.com/a/15674467/32090 – Boris Pavlović Jan 19 '18 at 07:10
  • 1
    @BorisPavlović Thanks, that's an interesting solution. – Eugene S Jan 19 '18 at 07:15
  • i think its late to comment but when i ran above program my o/p is differnt from yours.. `code` ChildClass.method1 IN BaseClass.method1 IN BaseClass.method3 IN BaseClass.method3 OUT BaseClass.method1 OUT ChildClass.method1 OUT . `code` – spandey Jan 19 '18 at 10:57

2 Answers2

3

A work around would be to create a private method in BaseClass and call that from method3 like this:

public class BaseClass implements BaseInterface {

    @Override
    public void method1() {
        System.out.println("BaseClass.method1 IN");
        this.internalMethod3();
        System.out.println("BaseClass.method1 OUT");
    }

    @Override
    public void method2() {
        System.out.println("BaseClass.method2 IN");
        System.out.println("BaseClass.method2 OUT");
    }
    private void internalMethod3() {

        System.out.println("BaseClass.method3 IN");
        System.out.println("BaseClass.method3 OUT");
    }

    @Override
    public void method3() {
        this.internalMethod3();
    }
}

Would accomplish the same thing

Also a comment about the solution posted in How to call a superclass method using Java reflection is that you should not do it this way if possible. Refactoring your code break it down to smaller functions would be the way to go here. As this question formulated there is no problem in refactoring the code.

jontro
  • 10,241
  • 6
  • 46
  • 71
  • you have changed the problem statement itself. This was intention to have the contract and then implement. – spandey Jan 19 '18 at 07:54
  • @spandey15 Not sure what you're saying and I don't see how this answer is different from what davidxxx posted. This fullfills the contract and is how I would do it if the need arises. – jontro Jan 19 '18 at 09:46
  • @spandey15 In Java, you don't have other solution because of overriding feature. I explain it in my answer. So you have to use a trick. – davidxxx Jan 19 '18 at 10:08
  • you too @davidxxx :) – jontro Jan 19 '18 at 10:31
  • @spandey15 Sorry, didnt see your edit when I updated the answer. Feel free to apply the edit again – jontro Jan 19 '18 at 10:38
2

It is the way which overridable methods work : at runtime, the method of the runtime object is invoked.
And here this.method3();, this is the runtime object and method3() an overridable method. So polymorphism takes place.

To achieve the expected behavior, you should so play with access modifiers by using the single one that doesn't allow overriding : private.
Delegate the method3() implementation into a private method and now you can access it from the method1() :

@Override
public void method1() {
    System.out.println("BaseClass.method1 IN");
    method3Internal();
    System.out.println("BaseClass.method1 OUT");
}

@Override
public void method3() {
    method3Internal();
}

private void method3Internal() {
    System.out.println("BaseClass.method3 IN");
    System.out.println("BaseClass.method3 OUT");
}
davidxxx
  • 125,838
  • 23
  • 214
  • 215