• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Polymorphism. Given a method defined only in the parent class, I am surprised to see this output

 
Ranch Foreman
Posts: 626
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
modified Sybex OCP-17 tb864615.OCPJAVASE17PT.c03.084

I have a method defined only in the parent class and members with the same name in both parent and child classes.
Given that I have a reference to a child instance, I expected  that invoking the parent method on it, would always refer to the child member.
RocketShip extends Ship and I have a RocketShip reference.
I am surprised to see that the parent method always refers to the parent member.

OUTPUT


get specs using this  3,5    2,4
get specs without using this 3,5    2,4









 
Saloon Keeper
Posts: 15630
366
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Your confusion is caused by one or two mistakes in your understanding.

First, polymorphism only applies to non-private instance methods. It doesn't apply to fields. So when the Ship class refers to weight or height, it will always be the weight or height field that is a member of the Ship class, not the field that is declared in the RocketShip class. Fields also don't override each other: RocketShip.weight is a completely different and unrelated field to Ship.weight.

Secondly, it appears that you think think line 10 in the Ship class should do something different than line 18, just because you used the this keyword. The two lines mean exactly the same thing, regardless of whether you used the this keyword: Access Ship.height on the current object. You should treat the this keyword as if it's a special hidden method parameter with the same type as the enclosing class:
 
Anil Philip
Ranch Foreman
Posts: 626
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you for your reply.
It is a RocketShip instance, not a Ship.

There is only one 'this'. Is that statement correct?
If so, shouldn't 'this' refer to the RocketShip data?
 
Marshal
Posts: 79467
379
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Anil Philip wrote:. . . a method defined only in the parent class . . .

Please don't say parent class and child class, even though many people do. Say superclass and subclass (or subtype). Maybe the C# terms, base class and derived class, are better.

members with the same name in both . . . classes.

What sort of members? Do you mean fields with the same name? Please use the correct terminology; that will make it much easier to get good answers.
It is usually a bad idea to have fields with the same name in a superclass and a subclass. Since fields are not polymorphic (as Stephan has already told you), they undergo static/early/compile‑time binding and that can cause no end of confusion.
I take it you realise that Stephan's code with this is a concept rather than an example that will actually compile.
Please don't quote the whole of the preceding post; that adds nothing new and is liable to removal.
 
Campbell Ritchie
Marshal
Posts: 79467
379
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Anil Philip wrote:. . . It is a RocketShip instance, not a Ship. . . .

If RocketShip extends Ship, then that instance is a Ship instance. It is an instance of both types.

There is only one 'this'. Is that statement correct? . . .

Not quite. If you are in nested types, then there may be more than one example of this.
 
Anil Philip
Ranch Foreman
Posts: 626
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:
It is usually a bad idea to have fields with the same name in a superclass and a subclass..


This is a practice question (adapted) from Boyarsky's OCP17-829 book
 
Anil Philip
Ranch Foreman
Posts: 626
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:

Anil Philip wrote:. . . It is a RocketShip instance, not a Ship. . . .

If RocketShip extends Ship, then that instance is a Ship instance. It is an instance of both types.

There is only one 'this'. Is that statement correct? . . .

Not quite. If you are in nested types, then there may be more than one example of this.



in the RocketShip example, isn't there only one 'this'?
 
Sheriff
Posts: 9708
43
Android Google Web Toolkit Hibernate IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:First, polymorphism only applies to non-private instance methods. It doesn't apply to fields. So when the Ship class refers to weight or height, it will always be the weight or height field that is a member of the Ship class, not the field that is declared in the RocketShip class. Fields also don't override each other: RocketShip.weight is a completely different and unrelated field to Ship.weight.



I think this kind of explains most of your questions. Any method in Ship class cannot see variables defined in any sub-class. Also public int getWeight() { return weight; } and public int getWeight() { return this.weight; } mean the same thing at runtime (in this case where there is no variable in the method which shadows the class field).
 
Anil Philip
Ranch Foreman
Posts: 626
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Ankit Garg wrote: Any method in Ship class cannot see variables defined in any sub-class. Also public int getWeight() { return weight; } and public int getWeight() { return this.weight; } mean the same thing at runtime (in this case where there is no variable in the method which shadows the class field).



Even though it is a method in the Ship class, since there is only one 'this' and it is the RocketShip instance that was created, then shouldn't refer to the rocketShip.weight?
 
Stephan van Hulst
Saloon Keeper
Posts: 15630
366
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Again, the 'this' keyword is almost exactly like a method parameter. And just like any other variable, it has a 'compile-time type'.

Take a look at this example:

The 'that' parameter does in fact refer to an object with type RocketShip. However, the field that is accessed depends only on the compile-time type of the object reference. It doesn't matter whether 'that' in getWeightOfThatShip() actually refers to a RocketShip or another type of Ship. The 'that' parameter has compile-time type Ship, and therefore that.weight will refer to Ship.weight, not RocketShip.weight.

Now, replace 'that' with 'this' and the application will work exactly the same way.
 
Anil Philip
Ranch Foreman
Posts: 626
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:Again, the 'this' keyword is almost exactly like a method parameter. And just like any other variable, it has a 'compile-time type'.

Take a look at this example:

The 'that' parameter does in fact refer to an object with type RocketShip. However, the field that is accessed depends only on the compile-time type of the object reference. It doesn't matter whether 'that' in getWeightOfThatShip() actually refers to a RocketShip or another type of Ship. The 'that' parameter has compile-time type Ship, and therefore that.weight will refer to Ship.weight, not RocketShip.weight.

Now, replace 'that' with 'this' and the application will work exactly the same way.



Thank you - it is a bit clearer to me now but for this point: When I step through it in the debugger, I see that this.weight is the value in RocketShip (see screenshot) this.weight = 2
But when I output the value, it outputs the value in Ship. Confusing.



Console output:

getWeightOfThatShip this.weight 3



rocket-ship.png
rocket-ship debugger output
rocket-ship debugger output
 
Stephan van Hulst
Saloon Keeper
Posts: 15630
366
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Anil Philip wrote:When I step through it in the debugger, I see that this.weight is the value in RocketShip (see screenshot) this.weight = 2
But when I output the value, it outputs the value in Ship. Confusing.


Let that be a lesson: IDEs often use labels that may be confusing if you take them to mean something specific. The IDE's graphical user interface is generally not created by the same developers that have busied themselves with the language specification in depth.

In this case, the 'this' label in your IDE is really just that: A textual label that refers to the current object. It doesn't really work like the actual 'this' keyword.
 
Anil Philip
Ranch Foreman
Posts: 626
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:
Let that be a lesson: IDEs often use labels that may be confusing
In this case, the 'this' label in your IDE is really just that: A textual label that refers to the current object. It doesn't really work like the actual 'this' keyword.



Thank you!
 
reply
    Bookmark Topic Watch Topic
  • New Topic