user3209450
user3209450

Reputation: 55

Why upcasting does not show runtime polymorphism?

I wrote a code to understand runtime polymorphism...

class S{
     int i=1;
    void m(){
        System.out.println("sssssssssssssssssssss");
    }
}
public class A extends S{

    int i=2;

    void m(){
        System.out.println("aaaaaaaaaaaaaaaaaaaaaaaa");
    }

    public static void main(String[] args) {
        S a=(S)new A();
        System.out.println(a.i);
        a.m();
    }
} 

Instance variable are subject to compile time binding, but why down casting of object of A does not meaning here? Means it's invoking A's method not S's method?

Upvotes: 0

Views: 1088

Answers (2)

Dawood ibn Kareem
Dawood ibn Kareem

Reputation: 79838

The variable a is a reference of type S to an object whose class is A. When you call m() on that object, you'll always get the version of m() in class A being called, because that's the class of the object, no matter what type of variable is referencing it. That's what polymorphism is about. The version of m() that gets called depends on the class of the object, not the type of the referring expression.

However, this object actually contains two variables called i - one declared in class A and the other in class S. Which one of these you get depends on the type of the referring expression that you use. Since the variable a is of type S, the expression a.i refers to the one that is declared in class S.

Upvotes: 0

Marko Topolnik
Marko Topolnik

Reputation: 200158

S a = (S)new A();

Let's see what you have here:

  1. variable a, of the reference type S;
  2. an instance creation expression yielding an object of type A, where A extends S;
  3. a reference upcast expression, upcasting the above expression into type S;
  4. the assignment of the result of 3. into the variable a.

What you must keep clear in your mind when reading Java is the distinction between:

  • the type of the object: an object can never change its type. In your example, the object is of type A;
  • the type of the reference: in your example, you converted a reference initially of type A into a reference of type S. You assigned that reference to a.

When you invoke a method on an object, the actual method invoked does not at all depend on the type of the reference, but only on the type of the object itself. The type of your object is A therefore the method in type A is invoked.

On the other hand, when you access an instance variable, polymorphism does not apply and the type of the reference becomes essential. With a.i you access i declared in the supertype S, and with ((A)a).i you access i from A. Note that the class A posseses two instance variables, both named i, and you can refer to each individually.


A note on terminology

The term "type of a reference" is actually a shorthand for the more correct "type of the expression yielding the reference." It is a purely compile-time artifact: there is no type information associated with a reference at runtime, it's just a bit pattern. Contrast this with the type of the object, which is a purely runtime artifact: the compiler doesn't in general know the type of the object involved in an expression, it only makes assertions about it. When such an assertion fails at runtime, the result is a ClassCastException.

Upvotes: 3

Related Questions