aspose file tools*
The moose likes Java in General and the fly likes Calling overridden methods from a constructor Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Soft Skills this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Calling overridden methods from a constructor" Watch "Calling overridden methods from a constructor" New topic
Author

Calling overridden methods from a constructor

Andrew Keidel
Greenhorn

Joined: Dec 06, 2001
Posts: 27
Howdy!
I think this question is an interesting one.
Imagine this situation:
1. We have a class Base with public method makeReady().
2. Base calls makeReady() from within its constructor.
3. We make a class Derived that extends Base and overrides the makeReady() method.
My question is this: What happens when we try: "Derived d = new Derived();"? More specifically, when the constructor in Derived calls Base's constructor (which is always done because Base is its parent class), Base's constructor calls the makeReady() method... who's makeReady() method does it call?
If you think the answer is obviously that in this case, Derived's makeReady() method is called by Base's constructor, you may be right about the answer (I'm not sure), but you're wrong that it's obvious. In C++, the above scenario does NOT work this way. Instead, in C++, when Base's constructor is called through Derived's constructor, the virtual makeReady() method call in Base's constructor will use Base's own makeReady() method.
I don't understand why this happens in C++, and I don't know what happens in Java. It's easy enough to test this out with code, but what I'm more curious about is the REASON why each language works the way it does.
Here is a link to the C++ explanation, which I don't fully understand:
http://www.research.att.com/~bs/bs_faq2.html#vcall
Help, please! Thanks!
Manfred Leonhardt
Ranch Hand

Joined: Jan 09, 2001
Posts: 1492
Hi Andrew,
Ditto for java ... works exactly as explained in the article.
OBVIOUS: base called before derived is created therefore no derived class to override called method!
Regards,
Manfred.
Cindy Glass
"The Hood"
Sheriff

Joined: Sep 29, 2000
Posts: 8521
So the question is - at the point when the makeReady() method is called - is the thing calling the method a Base or a Derived?
During Construction the JVM walks up the constructor chain to the highest point and then proceeds to construct each class on the way down.
So first the JVM creates an Object instance (no brainer), then it constructs the Base stuff. It is during this activity that the method makeReady() is called. So it is a Base that is calling the method - the Base version is used. After this the Derived constructor is finally added to the party. If the Derived constructor were to also make a call to the makeReady() method, then it would be overridden and that time the Derived version would be used.
Of course if you make such a call from OUTSIDE the class constructors (a more typical use), as in:
Base b = new Derived();
b.makeReady(); //uses the Derived version
it is easier to see that it is a Derived object that is making the method call, so the Derived version is used.


"JavaRanch, where the deer and the Certified play" - David O'Meara
Irene Loos
Ranch Hand

Joined: Apr 15, 2002
Posts: 78
Hi Andrew,
You may greatly benefit from "How my Dog learned Polymorphism" article on http://www.javaranch.com/campfire.jsp. It also talks about differences beetwen Java and C++.
Irene


Irene Loos
Geoffrey Falk
Ranch Hand

Joined: Aug 17, 2001
Posts: 171
    
    1
Nice explanation, but according to my experiment with jdk1.3.1, it is wrong. The Derived method gets called in both cases. What is the logic behind that?
It is a bad idea to call non-final or non-private methods from a constructor. Enlightenment is found here:
http://mindprod.com/gotchas.html#CONSTRUCTORINIT
Geoffrey
[ May 04, 2002: Message edited by: Geoffrey Falk ]
[ May 04, 2002: Message edited by: Geoffrey Falk ]

Sun Certified Programmer for the Java 2 Platform
Andrew Keidel
Greenhorn

Joined: Dec 06, 2001
Posts: 27
Thanks, Geoffrey!
So, Manfred and Cindy, it seems that you are both mistaken. Indeed, the method of the derived class is called from the constructor of the base class!
Manfred, you should not state something as "OBVIOUS" unless it is both obvious *and* correct.
Below is sample code for proving that Java works as Geoffrey and I fear. I am still hoping that someone can explain this question: *WHY* DOES JAVA WORK THIS WAY? Manfred, I believe that Java perhaps ought to work the way you describe, and the way C++ works, but apparently it does not. And the article Geoffrey points out highlights the problems that can result from this peculiarity of the Java language.
SAMPLE CODE:
class Base {
Base() {
doIt();
}
public void doIt() {
System.out.println("BASE");
}
}
public class Derived extends Base {
public void doIt() {
System.out.println("DERIVED");
}
public static void main(String args[]) {
Derived d = new Derived();
}
}
Geoffrey Falk
Ranch Hand

Joined: Aug 17, 2001
Posts: 171
    
    1
I think the compiler ought to give a warning or an error, if you try to call a non-final and non-private method from a constructor. This would avoid all such problems.
[ May 04, 2002: Message edited by: Geoffrey Falk ]
Dirk Schreckmann
Sheriff

Joined: Dec 10, 2001
Posts: 7023
Andrew & Geoffrey,
You are mistaken.


[How To Ask Good Questions] [JavaRanch FAQ Wiki] [JavaRanch Radio]
Dirk Schreckmann
Sheriff

Joined: Dec 10, 2001
Posts: 7023
Consider:
Andrew Keidel
Greenhorn

Joined: Dec 06, 2001
Posts: 27
Hi Dirk,
We are not mistaken.
The code you've provided is exactly my point. Sure, constructing a new Base works as we'd expect. The question was whether constructing a new Derived uses the doIt() method from Base or from Derived.
The initial explanations given in this thread said "new Derived()" used the doIt() method from Base. That is incorrect. In fact, it uses the doIt() method from Derived. The problem here is that if Derived has its own member variables that get initialized in its constructor and that are used by its doIt() method, we will be calling a method that incorrectly assumes it is using initialized variables.
Andrew Keidel
Greenhorn

Joined: Dec 06, 2001
Posts: 27
An explicit example of the problem being discussed is given below. Compiling and running this will give a runtime error (NullPointerException).

class Base {
Base() {
doIt();
}
public void doIt() {
System.out.println("BASE");
}
}
public class Derived extends Base {
public Integer myInt;
public Derived() {
super();
myInt = new Integer(77);
}
public void doIt() {
System.out.println("DERIVED");
System.out.println(myInt.toString());
}
public static void main(String args[]) {
Derived d = new Derived();
}
}
Dirk Schreckmann
Sheriff

Joined: Dec 10, 2001
Posts: 7023
You know what, I read Cindy's post too quickly, and so the rest of the posts were viewed in the wrong light. My previous assertion of the mistaken parties was itself mistaken.
Andrew Keidel
Greenhorn

Joined: Dec 06, 2001
Posts: 27
One more thing... Manfred and Cindy, sorry if I sounded rude before. I do greatly appreciate your input. I think I got a little surprised by the explanations and especially the use of the word "obvious." That's all.
Cheers,
Andy
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
My previous assertion of the mistaken parties was itself mistaken.
"We apologise again for the fault in the subtitles. Those responsible fot sacking the people who jave just been sacked, have been sacked."
I think the compiler ought to give a warning or an error, if you try to call a non-final and non-private method from a constructor. This would avoid all such problems.
Agreed. A warning at least would be appropriate, since it can easily lead to confusion.
Here's another demonstration for those who aren't sure what's going on:

This has output:

Note that when the Base constructor is called from within the Sub constructor, "this" clearly refers to an instance of Sub, not Base. Even though "this" has not been completely constructed yet, the JVM knows what class it will ultimately be. This is how it's able call overriding methods from the constructor - for better or worse.


"I'm not back." - Bill Harding, Twister
Cindy Glass
"The Hood"
Sheriff

Joined: Sep 29, 2000
Posts: 8521
Originally posted by Jim Yingst:
Note that when the Base constructor is called from within the Sub constructor, "this" clearly refers to an instance of Sub, not Base. Even though "this" has not been completely constructed yet, the JVM knows what class it will ultimately be. This is how it's able call overriding methods from the constructor - for better or worse.


Duh :roll: Thank you for straightening us out Jim. < sheesh Cindy >
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
This is very bad behavior on the part of Java. And there is really no way to change it because it would effect too many programs already written.


Associate Instructor - Hofstra University
Amazon Top 750 reviewer - Blog - Unresolved References - Book Review Blog
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Calling overridden methods from a constructor