3

I have abstract class Shape as below which contains abstarct method calc -

public abstract class Shape{
   public Shape(){
       System.out.println("from shape");
       calc();
   }

public abstract void calc();
}

Another class Circle which extends Shape -

public class Circle extends Shape{
 public Circle(){
    System.out.println("from Circle");
 }
     public void calc(){
        System.out.println("from calc in circle");
     }
}

And now the Final main class-

public class BasicsTest{
   public static void main(String [] args){
      Cirlce c=new Circle();
   }
}

Output when run the main class -

from shape

from calc in circle

from circle

I understand that when we create object of child class the construtor of parent class will be called. What i am confused about is how the call to calc method in shape's constrcutor works as we dont have any implementaion for the calc in shape class.

      public Shape(){
       System.out.println("from shape");
       calc();  // how the method from child class is being called ??
   }

From the output it seems it is calling the overridden calc method from the child class circle but how does that works ??

Thank you.

  • 2
    Related question http://stackoverflow.com/questions/3404301/whats-wrong-with-overridable-method-calls-in-constructors – Krishnanunni P V Apr 26 '16 at 12:50
  • @KrishnanunniPV's comment is more important than the current set of answers. Although you can call the method -- you would be calling a method in the not-yet-initialized subclass. It's better to avoid this. See also http://stackoverflow.com/questions/15327417/is-it-ok-to-call-abstract-method-from-constructor-in-java . – Andy Thomas Apr 26 '16 at 12:55
  • also putting a lot of functionality in a constructor is a bad idea, see http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/ – Nathan Hughes Apr 26 '16 at 12:55
  • Thanks for the references guyz – Akshay Panchakshari Apr 26 '16 at 13:17
  • An overridable inside the constructor is insane, as one is calling the child method in the base class constructor, when the child class construction still is not finished, see http://stackoverflow.com/a/36553063/984823 - your sense for troubles was indeed right. – Joop Eggen Apr 26 '16 at 13:52

4 Answers4

0

That's how polymorphism and inheritance work. It's important that you understand it if you're going to write object-oriented code.

The simplest explanation is to imagine that there's a method table that says "I know I'm an abstract class at compile time, but at run time I know that I'm a concrete child class. Look up the child's version of that method in the method table and call it." There's a measure of indirection that goes on at run time.

duffymo
  • 305,152
  • 44
  • 369
  • 561
0

You instantiate a Circle class in your test.

So what is happening in your Circle instance:

  • Circle constructor is called
  • super constructor is called
  • super constructor calls calc() method
  • calc() method of your Circle(!) instance is called

Note that you didn't instantiated a Shape but a circle. The crucial part then is really understanding how method overriding is working in OO: the calc() method is really just a virtual pointer to your actual implementation. Since you are instantiating a Circle, this will point to the overriden implementation in your Circle class

J. Dow
  • 563
  • 3
  • 13
  • 1
    but if you look at the output the program flow looks like below- 01) Shape constructor is called 02) calc() method from the Circle class is called(here i assume no circle object is created yet still it is able to call a method from Circle class!!) 03) Circle constructor is called – Akshay Panchakshari Apr 26 '16 at 13:09
  • It may look like this way, but it really isn't. The super() constructor call will be implicit before your System.out.println("from Circle"). So it goes Circle() -> Shape() -> (executing stuff in Shape constructor) -> return and go on executing stuff in circle constructor Also your instance is already in place when you enter the constructor. The is the reason why you can access members and methods via "this" – J. Dow Apr 26 '16 at 13:34
  • Yes you can call overridden methods of a derived (Circle) class from a super (Shape) class, but it's dangerous to do so because the derived (Circle's) constructor hasn't been called yet (for example it might initialize a `radius` value) and if your overridden method (like `calcArea`) depends on any of these fields being initialized in Circle's constructor, you'll get unexpected behavior (`radius` might be the default `0` or `null`). Overall it is hard to follow the code flow and difficult to debug. – MasterHD Mar 08 '23 at 10:52
0

Imagine it as a call to this.calc(). It doesn't call the method calc of the same class, it calls the method calc of this, and this is a Circle object.

dquijada
  • 1,697
  • 3
  • 14
  • 19
  • If you look at the program output it looks like the Circle constructor is being called at the end. So when the calc method is called there is no Circle object (or this) is available or created by that time. So not sure if this.calc() will work ? – Akshay Panchakshari Apr 26 '16 at 13:19
0

The answers of Jon skit and Eyal Schneider's from following post can be the possible answers for this question-

State of Derived class object when Base class constructor calls overridden method in Java

Community
  • 1
  • 1