views:

158

answers:

2

I tried with below example, it is working fine.

I expected it to pick sub-class's value since object won't be created for super class (as it is abstract). But it is picking up super class's field value only.

Please help me understand what is the concepts behind this?

abstract class SuperAbstract {
  private int a=2;
  public void funA() {
    System.out.println("In SuperAbstract: this.a "+a);
  }

}

class SubClass extends SuperAbstract {
  private int a=34;
}

I am calling new SubClass.funA();

I am expecting it to print 34, but it is printing 2.

P.S.: What I want to know is why using this in an abstract class not giving me an error?

As below text is emphasizing this would work on an instance and abstract classes won't have an instance.

Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this. from: http://java.sun.com/docs/books/tutorial/java/javaOO/thiskey.html

+6  A: 

Any field declared in a class is unique, even if it has the same name as a a field in a base class (i.e. only methods can be overridden, but not fields). Therefore, there are two distinct fields in the derived class: SuperAbstract.a and SubClass.a. The fact that the base class is abstract has no impact.

The abstract keyword simply signifies that a class cannot be instantiated, i.e. you cannot write new SuperAbstract(). You can only instantiate object of the subclass, which must override all methods marked abstract.

Jen
The fact that the field is `private` has nothing to do with it. It would be two different fields, even if the field in the super class was public.
aioobe
Good call. I corrected my answer.
Jen
+9  A: 

A) You can't override fields in that sense. Fields "are not virtual" like methods.

From http://www.janeg.ca/scjp/overload/overridingMethods.html

  • fields cannot be overridden but they can be hidden ie if you declare a field in a subclass with the same name as one in the superclass, the superclass field can only be accessed using super or the superclasses type

B) If you could, the field would probably have had to be at least protected :-)


since object won't be created for super class (as it is abstract)

It is actually instantiated.

The abstract keyword only ensures that, when instantiated, it's instantiated in the form of an extending class. When instantiating a Dog, you're at the same time instantiating an Animal! The this reference in the context of an Animal will thus always refer to a Dog or a Cat or whatever, but in all cases it refers to some Animal. :-)

As the example below illustrates, the this reference makes sense even in an abstract class:

abstract class Animal {
    public String name;

    public Animal(String name) {
        System.out.println("Constructing an Animal");
        this.name = name;
    }

    public abstract void speak();
}

class Dog extends Animal {
    public Dog(String name) {
        super(name);
        System.out.println("  Constructing a Dog");
    }
    public void speak() {
        System.out.println("Bark! My name is " + name);
    }
}

public class Test {
    public static void main(String... args) {
        new Dog("Woffy").speak();
    }
}

Prints:

Constructing an Animal
  Constructing a Dog
Bark! My name is Woffy

Update: The this reference refers to the same object in the super class as in the sub class.

You could try to add

public Animal getSuperThis() { return this; }

to the animal class, and do

System.out.println(this == getSuperThis());

in Dog.speak(). You would see that it prints true.

aioobe
Thanks aioobe. So, JVM actually instantiates two separate objects (one for super class, and one for sub class) and both will be stored separate in heap. Is my understanding right?
Reddy
No, it's the same object. See updated answer.
aioobe
Yes, it is printing true means both are same. But somehow distinction between super class and sub class is being maintained by JVM. I am saying this because in my program, super class's private variable (which won't be inherited) and it's value are just there for me to access them.
Reddy