-1

In the following code, I don't understand why when a1.k() is called, this.x in class C returns 100 instead of 1. My understanding is that this refers to the current object, but the static type of the current variable a1 is A. So shouldn't this.x returns 1, which is the variable for A type? I mean a1.x should return 1, right? Many thanks!

class A {
   public int x = 1;   
   public String k() { return "A" + this.x; }
}
class B extends A {
   public int x = 10;
   ...
}
class C extends B {
   public int x = 100;
   public String k() { return "C" + this.x; }
}
class TestABC {
   public static void main(String[] args) {
       A a1 = new C();
       C c1 = new C();
       System.out.println(a1.k());
   }
}
user3735871
  • 527
  • 2
  • 14
  • 31
  • There is no such thing as the static type of an object. What you are referring to is the static type of a variable or just the type of an expression. – Sotirios Delimanolis Sep 15 '14 at 04:35
  • `a1` shouldn't have a `k()` method, at compile time it's type is `A` correct? Also `x` from the `C` class is probably overriding the `x` from both `A` and `B`. – Yep_It's_Me Sep 15 '14 at 04:37
  • Sorry guys, yes I mean the static type of the variable a1 is A. Also I edited the question, originally I left out the k() method in class A. So yes k() in class C overrides the super Class k(). But what confuses me is that why a1.k() returns 100, when the static type of a1 is A. – user3735871 Sep 15 '14 at 04:47
  • Shadowing (redeclaring a member in a subclass) is (almost) never a good idea. Just don't do it. – Jim Garrison Sep 15 '14 at 04:57
  • possible duplicate of [java static binding and polymorphism](http://stackoverflow.com/questions/25830601/java-static-binding-and-polymorphism) – Joe Sep 15 '14 at 05:07

3 Answers3

1

This feature is called Dynamic Polymorphism. The methods being called is not dependent of type of its declaration but by the type being assigned to it (definition).

For this the classes must inherit and also override the methods in the parent class.

Here C,B extends A and overrides the method k;

if you try to call some C specific methods or variable it will throw error. (Since A doesn't know about that)

A is holding reference to C (pointing to C)

a1.k is actually C constructed Object and its new C().k() where x is 100 in C.

class Base{
    int x=10;
    public int getx(){return x;}
}

class Sub extends Base{
    int x=100;
    public int getx(){return x;}
}

class Test
{   
    public static void main (String[] args) 
    {
        Base b = new Base();
        Sub s = new Sub();
        System.out.println("sub: getx:"+s.getx()+" .x:"+s.x+" Class: "+s.getClass().getName());
        System.out.println("base: getx:"+b.getx()+" .x:"+b.x+" Class: "+b.getClass().getName());
        Base btoS = new Sub();
        System.out.println("btos: getx"+btoS.getx()+" .x:"+btoS.x+" Class: "+btoS.getClass().getName());
    }
}

Results in

sub: getx:100 .x:100 Class: Sub
base: getx:10 .x:10 Class: Base
btos: getx100 .x:10 Class: Sub
Dineshkumar
  • 4,165
  • 5
  • 29
  • 43
  • Thanks! I know the k() in class C should be called, instead of the k() in class A. But why this.x returns 100? I thought the instance variable is bounded to the static type. – user3735871 Sep 15 '14 at 04:53
1

When you call a1.k() you dynamically dispatch to the k method that is defined by the actual object whose reference is in a1. In this case, it is a C not an A or a B, and hence the k method is the override defined in C.

The static type (of a1 for example) is used for static resolution; e.g. resolving static methods, overload signatures, and fields. But for instance method invocation, the ultimate selection of the method to be invoked is dynamic.

I know the k() in class C should be called, instead of the k() in class A. But why this.x returns 100? I thought the instance variable is bounded to the static type.

Well it is. But it is the static type that determines which x is used by this.x in the k() call is the static type of this in the C.k method body!

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

Since you declare a1 as new C(), a1 will be seen as an object instance of class C, which overrides the fields of its parent class B and A. So why you would do things like A a1 = new C(); (or you might see a lot of such implementation), there is a recommendation saying "programming to interface rather than the actual implementation.", and I think this explains better.

Community
  • 1
  • 1
sytianhe
  • 31
  • 3