Why Is an Instance Variable of the Superclass Not Overridden by a Subclass

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.

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).

Why subclasses does not override the value of their superclass variable?

You are shadowing your field myvalue and not overriding it, I believe something like this will do what you want

public class a{
protected int myvalue = 1;
}

public class b extends a{
public b() {
myvalue = 2;
}
}

public class c extends a{
public c() {
myvalue = 3;
}
}

Also, please don't use Raw Types

// ArrayList<a> mylist = new ArrayList();
ArrayList<a> mylist = new ArrayList<>(); // <a> on Java 5 and 6

How to access overridden variable of subclass using instance of superclass

Make the variables private and add a getA() method in both classes, with the one in the subclass overriding the superclass.

public class Foo
{
static class Super{
private int a;
public int getA() { return a; }
}

static class Sub extends Super{
private int a = 10;
@Override
public int getA() { return a; }
}

public static void main(String args[]) {
Super sup1 = new Super();
Super sup2 = new Sub();
Sub sub = new Sub();
System.out.println(sup1.getA());
System.out.println(sup2.getA());
System.out.println(sub.getA());
}
}

This outputs

0
10
10

What is the use instance variable in superclass , and how to change their values in subclasses

The importance of instance variables in superclasses is that they will be inherited by all the subclasses of that superclass, reducing code redundancy. To alter the value of set the value of a private instance variable from a superclass use the super keyword in the constructor of the subclass. To alter the value of the instance variable after instantiation use a mutator (setter) method defined in the superclass. By convention the mutator method would be named setVariable().

Instance variable, when re-initialised in sub class' initialization block, is overridden like instance method, which it should not

It cannot be overridden, but it is inherited by child classes as long as it wasn't private in the parent. And they can access it, including both reading and writing it.

Overriding is creating a new member which is part of the current class, which has the same definition of the member of the parent class, and for that member to be accessed when you use the object polymorphically.

For example:

class Parent {
public int age = 50;
}

class Child {
public int age = 80;
}

Here we defined a new member, age, which is separate from the parent's age. If you access it from inside Child using this.age, you'll get 80. If you access the parent's age using super.age, you'll get 50.

But this is not overriding, because if you use the object polymorphically, it will access the parent's age:

Child childObj = new Child();
Parent parentObj = childObj;

System.out.println( childObj.age ); // Will print 80
System.out.println( parentObj.age ); // Will print 50

This is despite the fact that they are both the same object. That's because the child hides the field rather than override it.

Simply assigning a value in a field inherited from the parent is not overriding. It's part of what inheritance is all about.

What does it mean to say Instance variables are not over-rided in java?

It means if you call a method in a superclass it will resolve to the overriden version in a subclass (if your instance is a subclass). However a reference to a member variable will be bound to the declaration of that variable in the class from which the call is made.

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.

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