I need a clarification in Dynamic polymorphism of Java.
class Foo {
int a=3;
public void display() {
System.out.println(" in foo "+a);
}
}
class Bar extends Foo {
int a=8;
public void display() {
System.out.println(" in boo "+a);
}
}
public class Tester {
public static void main(String[]args) {
Foo f = new Bar();
f.display();
System.out.println(f.a);
}
}
Here when i create a child class object with a base class reference , while invoking the method f.display()
it gives me the output as in boo 8
. This is because of dynamic polymorphism which checks the object type at run time for invoking the method.
Now while printing f.a
it prints 3 because the variables cannot be overridden in java this is called hiding.That is why it is displaying the base variable value not the child variable value.
Now my question is f is a reference of base class which is pointing to the child class object. Then how f.a
points to the base variable.? what happens behind the scene ? How the reference is pointing to the base class ?
(I know the rules , but i want to know how/why ? )
Derived class pointer cannot point to base class.
To access the variable of the base class, base class pointer will be used. So, a pointer is type of base class, and it can access all, public function and variables of base class since pointer is of base class, this is known as binding pointer.
Runtime polymorphism can be achieved only through a pointer (or reference) of base class type. Also, a base class pointer can point to the objects of base class as well as to the objects of derived class. In above code, base class pointer 'b' contains the address of object 'd' of derived class.
For polymorphism, you need virtual functions, besides having (and actually using) pointers to the base class. Try making attack a pure virtual function in the Enemy class, and use e.g. enemy1->attack() and enemy2->attack() instead. There is no polymorphism in your examples, since there are no virtual functions.
I don't know if this is outside what you've learned, but here it is. When you compile your code, the compiler generates byte code which the JVM executes.
The reference to the field Foo.a
in f.a
in the line
System.out.println(f.a);
gets compiled to
getfield #6 // Field Foo.a:I
where getfield
is a bytecode instruction which
get a field value of an object objectref, where the field is identified by field reference in the constant pool index (index1 << 8 + index2)
and the constant pool
Constant pool:
// [...]
#6 = Fieldref #20.#24 // Foo.a:I
// [...]
So the byte code is referencing the field in class Foo
, the declared type of the variable, rather than in the run time class type of the instance.
You can look at the generated byte code with the following command
javap -c -v YourClass
This is because of what you have already stated in your question:
variables cannot be overridden in Java
Therefore, reference f.a
is resolved statically at compile time, and it brings the compiler to Foo.a
, which is 3
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With