0

i am newbie in java and i usually used c++ i just wondering this code works

public class ParentClass {
    public void methodA() {
        System.out.println("This is Parent A Method");
        whoAmI();
    }

    public void methodB() {
        System.out.println("This is Parent B Method and I am Calling Method A");
        whoAmI();
        methodA();
    }
}

public class ChildClass extends ParentClass{
    @Override
    public void methodA() {
        System.out.println("This is Child A Method and I am Calling Parents Method A");
        whoAmI();
        super.methodA();
    }

    @Override
    public void methodB() {
        System.out.println("This is Child B Method and I am Calling Parents Method B");
        whoAmI();
        super.methodB();
    }
}
ChildClass c = new ChildClass();
c.methodB();

and I expected output like this

This is Child B Method and I am Calling Parents Method B
This is Parent B Method and I am Calling Method A
This is Parent A Method

but was

This is Child B Method and I am Calling Parents Method B
This is Parent B Method and I am Calling Method A
This is Child A Method and I am Calling Parents Method A
This is Parent A Method

so i realized that in java all non-static methods are by default virtual functions like virtual keyword in c++.

is there any way to make output like this?

This is Child B Method and I am Calling Parents Method B
This is Parent B Method and I am Calling Method A
This is Parent A Method
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • The code - as is - won't compile. Method `whoAmI()` is undefined. – Turing85 Aug 08 '20 at 09:14
  • he just forgot to show it to us, no biggie – J Asgarov Aug 08 '20 at 09:17
  • 1
    If you want to always call `methodA` of class `Parent` within `methodB` of `Parent`, then you could declare`methodA` in `Parent` as `final` or `private`, preventing it from being overwritten. If this is not an option, then there is no way to do what you want due to [dynamic dispatch](https://en.wikipedia.org/wiki/Dynamic_dispatch#:~:text=In%20computer%20science%2C%20dynamic%20dispatch,(OOP)%20languages%20and%20systems.) (my C++ knowledge is a bit rusty, but iirc, the behaviour in C++ should be the same). – Turing85 Aug 08 '20 at 09:18
  • whoAmI() is just plain display function. public void whoAmI() { System.out.println("I am instance Of B"); } – lovelydays95 Aug 08 '20 at 09:24
  • The only question here is *why* you expected that output. It isn't correct, and C++ would behave the same way as Java here, as long as the methods are `virtual`, which is the default in Java. – user207421 Aug 08 '20 at 09:38
  • Why are you trying to do this? – NomadMaker Aug 08 '20 at 10:34
  • i was studing java and in c++ there is virtual table to call function in runtime but in java there is no comments on this question. so i just want to know is there any way to ignore keyword virtual(c++) in java – lovelydays95 Aug 08 '20 at 17:53

3 Answers3

1

You can wrap the methodA's impl of ParentClass in a seperate private method:

public class ParentClass {
    public void methodA() {
        interMethodA();
    }

    private void interMethodA() {
        System.out.println("This is Parent A Method");
        whoAmI();
    }

    public void methodB() {
        System.out.println("This is Parent B Method and I am Calling Method A");
        whoAmI();
        interMethodA();
    }
}

And the ChildClass remains the same.

MaanooAk
  • 2,418
  • 17
  • 28
1

The code - as is - does not compile since method whoAmI() is undefined. By removing the calls to this method, I was able to reproduce the output.


From what I understand, you want to ensure that methodA in Parent is called from methodB in Parent. Since dynamic dispatching is used in Jjava to determine which actual implementation is called, we have to enforce that methodA cannot be overridden. As @MarquisofLorne pointed out, C++ uses dynamic dispatch aswell, if methodA is defined as virtual in Parent.

To enforce that dynamic dispatch always results in a call to Parent's methodA, there are two general approaches that come to my mind: declaring methodA as final and declaring methodA as private.


Approach one: declare methodA in Parent as final

When going down this route, Child cannot re-define methodA, i.e. the code would result in a compile-time error if methodA is not removed from Child.

Ideone demo


Approach two: declare methodA in Parent as private

This approach is similar to the first approach, but allows you to retain methodA in Child, albeit the @Override-annotation must be removed since private methods cannot be overridden.

Ideone demo

Turing85
  • 18,217
  • 7
  • 33
  • 58
  • C++ only uses dynamic despatch if you specify `virtual`, but it is the default in Java. This may be the root of the OP's problem. – user207421 Aug 08 '20 at 09:39
  • @MarquisofLorne huh... as I said... my C++ is rusty =) added this information to my answer. Thanks! – Turing85 Aug 08 '20 at 09:42
0

You got:

This is Child B Method and I am Calling Parents Method B
This is Parent B Method and I am Calling Method A
This is Child A Method and I am Calling Parents Method A
This is Parent A Method 

Instead of

This is Child B Method and I am Calling Parents Method B
This is Parent B Method and I am Calling Method A
This is Parent A Method

Simply Bacause, In Java calling methodA() or this.methodA() in your methodB() of ParentClass calls the method off of the calling object or instance, Yet the instance is an instanceof ChildClass. Java treats methodA() and this.methodA() as same. The this keyword in Java actually refers to the "currently running instance of the object you're using". Meaning, the overridding methodA() of ChildClass will be called instead of methodA() of ParentClass.

Here is a suggestion, to get the expected output, simply apply modifications on the overridding methodA() of ChildClass by commenting out the printing line. Otherwise reference this for more details.

Divin Irakiza
  • 317
  • 1
  • 7