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?
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 cangetFoo()
work? In the subclass context, it would be trying to return a value of a field of the wrong type!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.
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
Java instance variables cannot be overridden in a subclass. Java inheritance doesn't work that way.
In your example, there is no method hiding (or overriding or overloading) going on.
There is hiding of instance variables though. In class
child
, the declaration ofa
hides the declaration ofa
inparent
, and all references toa
in thechild
class refer to thechild.a
not theparent.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
How to Calculate a Time Span in Java and Format the Output
Jax-Rs - How to Return JSON and Http Status Code Together
File Upload with Java (With Progress Bar)
Java Garbage Collector - When Does It Collect
No-Throw Virtualmachineerror Guarantees
Get Only Part of an Array in Java
Java Lambda Stream Distinct() on Arbitrary Key
Java 8 Lambda Expressions - What About Multiple Methods in Nested Class
Converting JSON to Xls/CSV in Java
Read Whole Text Files from a Compression in Spark
Why Does This Go into an Infinite Loop
Filter Jacoco Coverage Reports with Gradle
Java Conditional Compilation: How to Prevent Code Chunks from Being Compiled