Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Question on Polymorphism

 
amol bakre
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I have done SCJP2 like years ago (..back in 2001!!..i know) and thought to upgrade my certification to Java 7, although m not really taking the upgrade exam, thought i will give the OCA JP7 and then the OCP JP7, never hurt to go through the concepts and fundamentals again. Anyway, as a part of my prep for the certification i came across this question that i thought was interesting and kinda confusing and would welcome some explanations:
The program:
The question is what will the program output when compiled and run. The answer to the question was given as 0, 10.
I dont know if m just being thick..but i thought it should be PolyParent and then 10, why m thinking this is because when you would do a new PolyChild() it will first try to construct all the parent (super) classes so Object and then PolyParents , and when PolyParent() is being executed then at that time, PolyChild will not have been initialized, so how come a call to print is going to PolyChild's print?? Also, it's not like that print is a static member of PolyChild, its an instance member which should've become known after Static initializers and PolyParents construction??!!


 
Liutauras Vilda
Bartender
Pie
Posts: 2792
112
BSD VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, always UseCodeTags (<- link to read) when you post actual code. I've added them for you, but code still not readable, because of bad indentation, misplaced curly braces and similar problems.

Is that code is meant to look like this?
 
amol bakre
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

Yep, it was meant to look like that, sorry about the formatting, i did use the tab and space in the editor but the editor then dropped all of that i suppose, it was the editor not mee!!!. Have read the link you provided will use the code tags in future, and thanks for formatting the program.

 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
amol bakre wrote:Anyway, as a part of my prep for the certification i came across this question that i thought was interesting and kinda confusing and would welcome some explanations

And where did you find this code snippet and question? Always QuoteYourSources please.
 
Kamil Hlubek
Ranch Hand
Posts: 49
2
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think the program works as follow ( please correct me if something is wrong ):




On line 1 a call to the constructor ( which is actually a default constructor ) of PolyChild is made to instantiate the PolyChild object. In this constructor super() is implicit called to instantiate the state of the superclass at first. Here ( in the constructor of PolyParent ) is the tricky part. The constructor calls the print() method, which is overriden by the subclass PolyChild and because the dynamic dispatch ( many other people say only polymorphism to it ) already exists before the object is fully instantiated, the constructor of PolyParent does not call print() from PolyParent, but from PolyChild.
On line 3, 0 is printed ( when the parent constructor calls it ), because the value of i is not set until after the super() statement of the PolyChild constructor.
On line 2, the print() method is executed, but the value i is already assigned to 10.

This is my first reply to explain somebody something and because I am preparing to my first exam ( OCAJP 8 ) , I hope much more you understand it and I did it well.
 
amol bakre
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And where did you find this code snippet and question? Always QuoteYourSources please.

noted, I found a similar question on one of the tests of enthuware.

I kind of figured why a '0' was printed and later a 10. What i cant get my head around is why the call to print() from contructor of Parent goes to print() of Child. Why is dynamic dispatch even being considered here as there we are not calling print() on any object from within the constructor!!

I changed the program to read:


and now the program outputs "Polyparent" both times.

So i'm guessing, the compiler has checked that print is a valid overridden method, object type is Child and the runtime has adhering to polymorphism called on the Child's print..
What if i had an init() method in both my classes <for some reason i did not want to use initialization blocks, but init() methods> then i will not be able to initialize my superclass to how i want that to be initialized,

But then i am thinking probably I would only override because i wanted to alter the behaviour in the parent, so this, what's happening is correct, i should just make a call to super.print() (from within Child.print()) if there was some importaint peice that needed to be executed.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Kamil Hlubek wrote:This is my first reply to explain somebody something and because I am preparing to my first exam ( OCAJP 8 ) , I hope much more you understand it and I did it well.

You are spot-on! Excellent explanation Have a cow!

In this topic you'll find a very detailed explanation (with a different code example) about what's going on if you call an overridden method in the parent class's constructor.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
amol bakre wrote:I kind of figured why a '0' was printed and later a 10. What i cant get my head around is why the call to print() from contructor of Parent goes to print() of Child. Why is dynamic dispatch even being considered here as there we are not calling print() on any object from within the constructor!!

Don't forgetis exactly the same as And this is a special reference variable which refers to the actual (current) object. So when you invoke new PolyChild(); you are creating a new PolyChild instance and so this will refer to this newly created object.

amol bakre wrote:and now the program outputs "Polyparent" both times.

That's normal, because PolyChild is not involved anymore if you just create a PolyParent instance.

amol bakre wrote:So i'm guessing, the compiler has checked that print is a valid overridden method, object type is Child and the runtime has adhering to polymorphism called on the Child's print..

That's exactly what happens!

amol bakre wrote:What if i had an init() method in both my classes <for some reason i did not want to use initialization blocks, but init() methods> then i will not be able to initialize my superclass to how i want that to be initialized,

And why do you want an init() method if you have constructors and initialization blocks to initialize the state of your objects. And it's actually considered a bad practice to invoke methods from the constructor which can be overridden, it might even cause hard to trace bugs (like you can see in this topic).

Hope it helps!
Kind regards,
Roel
 
Sachin Tripathi
Ranch Hand
Posts: 368
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You just need to know these things:
1-When we assign an object of subclass type to the reference variable of superclass type(using superclass polymorphically) then:
a-At compile time when any method is invoked then it checks in the class which is a type of reference variable.And binds some information with bytecode like return type of method etc

b-Now at runtime jvm is presented with only object of extended class type,so it checks for the method in that object as described in bytecode,like matches return type etc

So it runs the overrided method in your case


Now why it prints 0,is a matter of concern...

SO lets simplify that also,
when we create object of subclass( then all its and its superclasses field is created and initialized with default value,and as constructor of particular object operates it initializes its defined value )then its default constructoris invoked,in which implicitly defined
super();
is present.
Which calls superclass constructor,(which will call constructor of Object,and then again returns to superclass constructor)
Untill this point we have" i" (instance variable of subclass)=0;(as constructor of subclass hasn't operated completely.
Now superclass constructor operates ,it prints 0(value of i)

Now constructor of subclass executes and it assign 10 (explicitly defined value of i)to i
Then when print is invoked it prints 10(value of i)
 
Guillermo Ishi
Ranch Hand
Posts: 789
C++ Linux Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Something worth remembering here maybe is if PolyParent also contains an i, then System.out.println(pp.i) will use that i because variables come from the reference type not the object type. That is if you are making use of the reference, which is the normal thing.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sachin Tripathi wrote:b-Now at runtime jvm is presented with only object of extended class type,so it checks for the method in that object as described in bytecode,like matches return type etc

That's not true! Checking if the return type of the overriding method is valid (same return type or covariant return type) happens at compile time, not at runtime. That's why you'll get a compiler error if the return type is invalid. At runtime the JVM checks if the actual object defines an override of the method which is invoked. If it is, this method is executed; otherwise the parent class method will be executed.
 
Sachin Tripathi
Ranch Hand
Posts: 368
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel ,you misunderstood what i said

By checks means i meant that at compile time compiler defines the method signature's information in bytecode and order jvm to look for only that method that matches with the method signature as defined in bytecode.

At runtime jvm has only object of subclass,so it searches for only that method in that object,about which he was ordered for

If we override,then overrided one will be the method found in object,and executed
Else the method of superclass will be found and executed
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sachin Tripathi wrote:Roel ,you misunderstood what i said

Or maybe you explained it not very well...
 
amol bakre
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
THanks for all the replies,
Thanks Roel for the link, that was a good read, that thread, on this subject..Cheers
 
Sachin Tripathi
Ranch Hand
Posts: 368
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel,actually what you say is debatable.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sachin Tripathi wrote:By checks means i meant that at compile time compiler defines the method signature's information in bytecode and order jvm to look for only that method that matches with the method signature as defined in bytecode.

Just for the record: the compiler just creates some .class files. It doesn't order anything nor anybody to look for something. The JVM is smart enough to make that decision on its own, based on the type of the actual object (at runtime).
 
Sachin Tripathi
Ranch Hand
Posts: 368
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are deliberately focussed in finding mistakes

I was always taught that if you want to explain something difficult to understand,then try to present in humorous way
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sachin Tripathi wrote: I was always taught that if you want to explain something difficult to understand,then try to present in humorous way

I can only agree on one condition: that what's presented and/or explained is correct, otherwise the humorous explanation doesn't have any value at all.
 
Sachin Tripathi
Ranch Hand
Posts: 368
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Is this is not happening,

JVM uses method signature as described in .class file.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic