This week's book giveaways are in the Java EE and JavaScript forums.
We're giving away four copies each of The Java EE 7 Tutorial Volume 1 or Volume 2(winners choice) and jQuery UI in Action and have the authors on-line!
See this thread and this one for details.
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Why doesn't the subclass variable hide it? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of The Java EE 7 Tutorial Volume 1 or Volume 2 this week in the Java EE forum
or jQuery UI in Action in the JavaScript forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Why doesn Watch "Why doesn New topic
Author

Why doesn't the subclass variable hide it?

Kathy Hodgson
Greenhorn

Joined: Jun 16, 2003
Posts: 28
The code below is from one of Jamie Jaworski's practice test questions; I tried it and it does what he says it does but I don't understand why S1 prints for the String s instead of S2. The reference is to an instance of S2. S2 inherits display(), so why isn't that call printing S2's own String s instead of its parent's? I'd understand why if the instance was assigned to an S1 reference, but not as it stands, since I thought for a variable the reference type determined which you got. Could somebody please explain it?
Code:
public class Question{
String s = "Outer";
public static void main(String[] args){
S2 s2 = new S2();
s2.display();
}
}

class S1 {
String s = "S1";
void display() {
System.out.println(s);}
}
class S2 extends S1{
String s = "S2";
}
Alton Hernandez
Ranch Hand

Joined: May 30, 2003
Posts: 443
Originally posted by Kathy Hodgson:
The reference is to an instance of S2. S2 inherits display(), so why isn't that call printing S2's own String s instead of its parent's?
public class Question{
String s = "Outer";
public static void main(String[] args){
S2 s2 = new S2();
s2.display();
}
}

class S1 {
String s = "S1";
void display() {
System.out.println(s);}
}
class S2 extends S1{
String s = "S2";
}

Hi Kathy,
Because polymorphism does not work with variables. That is why we say we hide, and NOToverride, variables. When S1 is compiled, the variable s becomes statically bound to the display() method.
[ August 01, 2003: Message edited by: Alton Hernandez ]
Kathy Hodgson
Greenhorn

Joined: Jun 16, 2003
Posts: 28
Sorry, I still don't understand, because display() is inherited, and it is being called on s2. At compile time, Java knows that I want s2's display(), not s1's. So if I'm calling display from within the s2 class, and there is no object dot-operator prefix when the String s is passed to println from within s2's display, why doesn't the method assume that I want the String s of the class I'm calling the method of? I tried putting in a "this" before the s but got the same result - "S1." So the compiler thinks my instance will be an instance of S1 even though I have told it explicitly that my instance is an instance of S2.
The only way any of this makes sense to me is if the child class doesn't really have any method it inherits without overriding - in other words, it is not calling its own invisible copy of the display method (which is how I thought method inheritance worked) but is calling its parent's display method. If a child class inherits a method without changing it, doesn't it really have it at all?
Kathy
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Could somebody please explain it?

At compile-time when the compiler is converting the source code to byte codes (as opposed to run-time when the virtual machine is executing the bytes codes), the compiler has to resolve the identifier s.
System.out.println(s);
The compiler has to find a declaration of a variable s. The compiler looks for a local declaration, or a field declaration in the class, or a field declaration in a superclass or superinterface.
The compiler does not look for a declaration of a variable s in any of the subclasses.
String s = "S1";
The compiler finds a field declaration in class S1. The compiler tells the virtual machine to use the field of this class. The virtual machine never overrides that decision.
[ August 02, 2003: Message edited by: Marlene Miller ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
If a child class inherits a method without changing it, doesn't it really have it at all?

Think of each class as a description of an object � the attributes and operations declared by the class.
There are two descriptions, a full description and a segment description. The full description is the union of the declarations of a class and all its ancestors. The segment description is the difference between the full description and the parent description.
Inheritance allows a full description to be automatically constructed by assembling declaration fragments from an inheritance hierarchy. Inheritance is a mechanism for combining shared incremental descriptions to form a full description of an object.
That is inheritance. It is the incremental definition of an object.
(Extracted from the UML Reference Manual, Jim Rumbaugh.)
[ August 02, 2003: Message edited by: Marlene Miller ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
The only way any of this makes sense to me is if the child class doesn't really have any method it inherits without overriding - in other words, it is not calling its own invisible copy of the display method (which is how I thought method inheritance worked) but is calling its parent's display method.

(1) class B inherits a method from class A

(2) Where is the inherited method, in B or in A?
invokevirtual indexbyte1 indexbyte2
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the runtime constant pool of the current class, where the value of the index is (indexbyte1 << 8) | indexbyte2. The runtime constant pool item at that index must be a symbolic reference to a method, which gives the name and descriptor of the method as well as a symbolic reference to the class in which the method is to be found. The named method is resolved.
(3) What does it mean to resolve a named method? 5.4.3.3 Method Resolution
To resolve an unresolved symbolic reference from D to a method in a class C... Method resolution attempts to look up the referenced method in C and its superclasses
[ August 02, 2003: Message edited by: Marlene Miller ]
cyril vidal
Ranch Hand

Joined: Jul 02, 2003
Posts: 247
Note that if you override display() in S2:

then you get the expected S2 as output...because s in method display() of S2 'hides' s in method display of S1...


SCJP 1.4, SCWCD, SCBCD, IBM XML, IBM Websphere 285, IBM Websphere 287
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Kathy, sometimes when I get really interested in a question, I get carried away. It wasn't too long ago that I imagined the inherited method as somehow existing in the subclass. I hope I did not overwhelm you.
I think you are on the right track with your new way of thinking about inheritance. The questions you are asking are good ones.
Thinking about what the compiler has to do, how the compiler binds the name s to a declaration at compile-time is what helped me the most. Also working all 19 of Dan Chisholms exams helped.
Marlene
cyril vidal
Ranch Hand

Joined: Jul 02, 2003
Posts: 247
Also working all 19 of Dan Chisholms exams helped.

by example, about the difference between 'hiding' and 'overriding', you may find this example interesting: (the same process of hiding happens for both instance variables and static methods):
Dan's Mock exam Inheritance question n�12:

Output: P.printS1 Q.printS2
Dan's explanations:
Static method Q.printS1 hides the static method P.printS1 in the super class P. Instance method Q.printS2 overrides the instance method P.printS2. Due the the differences between the hiding of static methods and the overridding of instance methods the invocation of the two methods in P.printS1S2 produces different results. The method invocation expression printS1 results in the invocation of the hidden super class method P.printS1. The method invocation expression printS2 results in the invocation of the overridding sub class method Q.printS2.
Kathy Hodgson
Greenhorn

Joined: Jun 16, 2003
Posts: 28
Thanks to all of you, I'm finally getting a handle on this. I'm going to go through some of Dan Chisolm's exams this afternoon. Marlene, I can't claim that I understand everything you are writing, but certainly enough to help me rework my mental images, which seem to be what was getting in the way here. Your comments also make me aware of how much more there is for me to learn, which I think is a good thing!
Kathy
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Hi Kathy,
Do not worry about what I said. I did not learn all that at one time. I went way beyond what we need for the exam.
Dan's exam questions will help you to learn what you need to understand.
I found the best way to work Dan's exams is one question at a time with patience and active participation. After committing myself to an answer but before looking at his answer, I would do research on anything I was unsure of, looking in books or experimenting with code. Then I cut-and-pasted the class declaration into my editor, compiled and ran the program to see the output, compile-time error or run-time exception. Then I cut-and-pasted the result into the source code file. After a while I could predict the exact compiler error or run-time exception. Only then I read Dan's answer and cut-and-pasted the answer into an edit file, studied the answer and added some notes. His questions are so helpful, it is worth all that extra work.
I also kept score. I logged date, a count of wrong answers and the exact question numbers of wrong answers, almost wrong answers (my answer before looking at the options), tricky questions, and hard questions.
Marlene
[ August 03, 2003: Message edited by: Marlene Miller ]
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Why doesn't the subclass variable hide it?