Java Inheritance - Instance Variables Overriding

Why is an instance variable of the superclass not overridden by a subclass?

Why instance variable of a superclass is not overridden in subclass method see my code below ...

Because instance variables CANNOT be overridden in Java. In Java, only methods can be overridden.

When you declare a field with the same name as an existing field in a superclass, the new field hides the existing field. The existing field from the superclass is still present in the subclass, and can even be used ... subject to the normal Java access rules.

(In your example, an instance of C has two distinct fields called a, containing distinct values.)



Because instance variables CANNOT be overridden in Java, but why? why is it done in this manner in Java? What's the reason?

Why did they design it that way?

  1. Because overriding variables would fundamentally break code in the superclass. For example, if an override changes the variable's type, that is likely to change the behavior of methods declared in the parent class that used the original variable. At worst, it renders them uncompilable.

    For example:

       public class Sup {
    private int foo;
    public int getFoo() {
    return foo;
    }
    }

    public class Sub extends Sup {
    private int[] foo;
    ...
    }

    If Sub.foo overrides (i.e. replaces) Sup.foo, how can getFoo() work? In the subclass context, it would be trying to return a value of a field of the wrong type!

  2. If fields that were overridden were not private, it would be even worse. That would break the Liskov Substitutability Principle (LSP) in a pretty fundamental way. That removes the basis for polymorphism.

  3. On the flipside, overriding fields would not achieve anything that cannot be done better in other ways. For example, a good design declares all instance variables as private and provides getters/setters for them as required. The getters/setters can be overridden, and the parent class can "protect" itself against undesirable overrides by using the private fields directly, or declaring the getters/setters final.


References:

  • Java Tutorial - Hiding Fields
  • JLS Example 8.3.1.1-3 - Hiding of Instance Fields.

Java inheritance overriding instance variable

  1. Java instance variables cannot be overridden in a subclass. Java inheritance doesn't work that way.

  2. In your example, there is no method hiding (or overriding or overloading) going on.

  3. There is hiding of instance variables though. In class child, the declaration of a hides the declaration of a in parent, and all references to a in the child class refer to the child.a not the parent.a.

To illustrate this more plainly, try running this:

public static void main(String args[]) throws IOException {
child c1 = new child();
parent p1 = c1;

System.out.println("p1.a is " + p1.a);
System.out.println("c1.a is " + c1.a);
System.out.println("p1 == c1 is " + (p1 == c1));
}

It should output:

    p1.a is 10
c1.a is 11
p1 == c1 is true

This demonstrates that there is one object with two distinct fields called a ... and you can get hold of both of their values, if the access permits it.


Finally, you should learn to follow the standard Java identifier conventions. A class name should ALWAYS start with a capital letter.

Java Inheritance - instance variables overriding

Because inheritance is intended to modify behaviour. Behaviour is exposed through methods, and that's why they can be overridden.

Fields are not behaviour but state. You don't need to modify that, nor the private methods employed by the superclass. They are intended to allow the superclass to do it's job.

Java Inheritance: How to override instance variables/fields from parent class?

Your parent class instance variables are Private to that, so you can't update them from Child class. So rather you use parameterize method or create Protected setter/getter for instance variables (or protected variable itself). In you your case the variables are final so you actually can't even update them. So technically that's not possible to use child class variables in parent class.

If you update your variable to protected and remove static/final modifiers (as you mentioned in comments that you can). Before calling method from parent class, update variable data before calling super method. You can do it as below:

Approach 1 : Updating data in parent class before calling parent class method.

Parent Class:

public class ParentClass {

protected String firstName = "Billy Ray";
protected String lastName = "Cyrus";
protected int age = 58;
protected String city = "Hunstville";

public boolean methodIWantToReuse() {
// Passing in the objects created above as argument, which have the Parent
// instance variable data
Object1 obj1 = new Object(firstName, lastName);

Object2 obj2 = new Object(age,city);

Object3 obj3 = new Object(obj1, obj2);

Object4 obj4 = new Object(obj3);
return someRandomMethodHere(obj4);;
}
}

Child Class:

public class ChildClass extends ParentClass {
protected String firstName = "Miley";
protected String lastName = "Cyrus";
protected int age = 27;
protected String city = "Los Angeles";

public boolean methodIWantToReuse() {
// Update data in Parent class first

super.firstName = firstName;
super.lastName = lastName;
super.age = age;
super.city = city;
return super.methodIWantToReuse();
}
}

Approach 2 : If you want to use parameterized method to make it stateless, you can do it as below:

Parent Class:

public class ParentClass {

protected String firstName = "Billy Ray";
protected String lastName = "Cyrus";
protected int age = 58;
protected String city = "Hunstville";

public boolean methodIWantToReuse() {

return methodIWantToReuse(this.firstName, this.lastName, this.age, this.city);
}

public boolean methodIWantToReuse(String firstName, String lastName, int age, String city) {
// Passing in the objects created above as argument, which have the Parent
// instance variable data
Object1 obj1 = new Object(firstName, lastName);

Object2 obj2 = new Object(age,city);

Object3 obj3 = new Object(obj1, obj2);

Object4 obj4 = new Object(obj3);
return someRandomMethodHere(obj4);;
}
}

Child Class:

public class ChildClass extends ParentClass {
protected String firstName = "Miley";
protected String lastName = "Cyrus";
protected int age = 27;
protected String city = "Los Angeles";

public boolean methodIWantToReuse() {
// Update data in Parent class first
return super.methodIWantToReuse(this.firstName, this.lastName, this.age, this.city);
}
}

NOTE: It's not good practice to keep local variables name same as the class level variables. But kept it here same for just understanding.

Overriding a super class's instance variables

Because if you changed the implementation of a data member it would quite possibly break the superclass (imagine changing a superclass's data member from a float to a String).

Is there a way to override class variables in Java?

Yes. But as the variable is concerned it is overwrite (Giving new value to variable. Giving new definition to the function is Override). Just don't declare the variable but initialize (change) in the constructor or static block.

The value will get reflected when using in the blocks of parent class

if the variable is static then change the value during initialization itself with static block,

class Son extends Dad {
static {
me = "son";
}
}

or else change in constructor.

You can also change the value later in any blocks. It will get reflected in super class

Overriding member variables in Java ( Variable Hiding)

When you make a variable of the same name in a subclass, that's called hiding. The resulting subclass will now have both properties. You can access the one from the superclass with super.var or ((SuperClass)this).var. The variables don't even have to be of the same type; they are just two variables sharing a name, much like two overloaded methods.

Inherited class variables when initialized are overriding own value setted by parent

Your problem here is super() calls the parent constructor, which calls init(). The strName = ""; statement is then run inside the child class constructor after the super() call.

strName should be a protected variable in the parent class if you want to set it up like that. Otherwise, you should just bite the bullet and manually initialize it in the constructor after the call to super(); That's the safest and most predictable way to do this.

Instance variable in derived class has the same name with private instance variable of superclass?

Yes it is possible to declare such a variable, because the variable in the super class is private it cannot be seen in the child class and so there is no conflict.

But note that this is not the same as 'overriding', where an externally visible member is hidden by one with the same name in a child class.



Related Topics



Leave a reply



Submit