• Post Reply Bookmark Topic Watch Topic
  • New Topic

inheritance and redefined instance variables  RSS feed

 
Al Finlay
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello I'm trying to understand why the following example produces two different values for the instance variable position.



Through constructor chaining I would expect the instance variable position to hold the value 15 but the line marked (2) prints the value 10.
I have noticed that if the line marked (1) is changed to ..

then the line marked (2) does return 15

I understand this is an unreal scenario but I would like to understand why this occurs.
Any help would be greatly appreciated.
 
Henry Wong
author
Sheriff
Posts: 23283
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Welcome to the ranch...

Al Finlay wrote:


Through constructor chaining I would expect the instance variable position to hold the value 15 but the line marked (2) prints the value 10.



Don't know what you mean by constructor chaining, but an instance of TFrog has two position instance variables. One defined by the TFrog class, and the other defined by its super class. Polymorphism is not supported for instance variables, and the compiler chooses the instance variable to use based on the type of the reference variable used to access it.

Al Finlay wrote:
I have noticed that if the line marked (1) is changed to ..

then the line marked (2) does return 15

I understand this is an unreal scenario but I would like to understand why this occurs.
Any help would be greatly appreciated.


So... change the type of the reference, and change which instance variable to get.

Henry
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just as a side note, I see that in once case you refer to "position" and in another case you refer to "this.position." In both those cases, including "this." is the same as leaving it out.
 
Al Finlay
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the quick reply. So an instance of TFrog has two instance variables named position. But in your reply you said the compiler chooses which instance variable based on the type of variable .. but both lines use the same variable? The only difference I can see is that one line uses direct access and the other line uses indirect access (through a method). Why does the method use the copy of the instance variable from the superclass when the method is overridden in the subclass?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Al Finlay wrote:Thanks for the quick reply. So an instance of TFrog has two instance variables named position. But in your reply you said the compiler chooses which instance variable based on the type of variable .. but both lines use the same variable? The only difference I can see is that one line uses direct access and the other line uses indirect access (through a method). Why does the method use the copy of the instance variable from the superclass when the method is overridden in the subclass?


When you call an overridden method, which class's version of that method to call is determined at runtime. So if TFrog and Frog both define the same (non-static, non-private, non-final) method, then, regardless of what type of variable s is, TFrog's version of the method gets called.

Now, inside the method body, if we refer to a member variable, what matters is the type of the "this" reference. If we're in TFrog's method, position (same as this.position) is TFrog's position variable. If we're in Frog's method, then position (same as this.position) is Frog's variable. Note that if TFrog didn't have it's own position variable hiding Frog's, then TFrog's position/this.position would refer to the same variable as Frog's.

When you refer to s.position, since s is of type Frog, it's Frog's variable that we're referring to. This is determined at compile time by the declared reference type of s, and is not affected by what the class of the object is at runtime.

The only thing that's affected by what the class of the object is at runtime is which class's version of a specific signature (with that exact signature being determined at compile time) of a non-static, non-private, non-final method to call.

I know it seems confusing, but the rules are actually fairly simple and straightforward. They're just not necessarily easy to explain or to really get your head around from textual explanations.

And in real-world programs, stuff like this is rarely a problem, because people should and usually do follow the principles that A) You keep your member variables private (or, in a few cases, maybe, protected), and B) You don't knowingly name a subclass variable the same as a superclass variable.
 
Al Finlay
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the help Jeff, really good explanation.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're quite welcome. Glad you found it helpful.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!