Search code examples
javacastingreferencefieldtyping

Java wider object assignment conversion


In the following example, I don't understand why Base b1 = new Derived(); System.out.println(b1); prints out x=10, z=20. My understanding is that since b1 has a static type of Base, it don't have access to the fields in Derived, so z shouldn't haven been printed out. Can someone please help to explain? Many thanks!

class Base {
  int x;
  public Base1() { x = 10; }
  public Base1(int x) { this.x =x; }
  public String toString() {
     return "x=" + x ;
  } 
 }
 class Derived1 extends Base1 {
     int z = x * 2;
     public Derived1() {}
     public Derived1(int x, int z) {
        super(x);
        this.z = this.z + z;
     }
     public String toString() {
        return "x=" + x + ", z=" + z;
     }
  }

Solution

  • The object is a Derived, not a Base. Your interface to the object from b1 is Base. Base has toString, so you can access toString. The implementation you access is the one the object has, which is provided by Derived, which uses z. The implementation of Derived#toString can access z because its reference to the object is via a Derived reference (this), not a Base reference.

    As Oli points out in a comment, this is fundamental to polymorphism — having the behavior of the object depend on the object rather than the interface to the object.

    If the internals of the object were dictated by the interface we had to it, we'd be in a fair bit of trouble trying to implement interfaces! :-)