This question already has answers here:
Java Inheritance - instance variables overriding
(3 answers)
Closed 10 years ago.
I am learning java. I have a doubt in inheritance. When a child class extends parent class and parent class has a method which refers to a instance variable declared in parent. But the child class dint override this method and has declared instance variable with same name as the parent. In this case instance variable from child will be referred or parent will be referred. Below is the code snippet
class Parent {
int a;
Parent() {
System.out.println("in Parent");
a = 10;
}
void method() {
System.out.println(a);
}
}
class Child extends Parent {
int a;
Child() {
System.out.println("in Child");
a = 11;
}
}
public class Test {
public static void main(String args[]) throws IOException {
Parent p1 = new Child();
p1.method();
}
}
The output I get is
in parent
in child
10
Can someone please make me understand why its referring parent class's instance variable a and not child class's a.
Another doubt is, I understood hiding the method, when there is a static method in parent and child class also has declared a static method with same signature. Here hiding means ? what method is getting hidden ? If its the parent method can you please explain me ?
Thanks in advance.
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 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.
Instance variables are not overriden in sub-class. If you define a variable in your class with the same name as in your super class it's called shadowing of variables inheritance and polymorphism doesn't apply for instance variables. if you define method() in parent and override it in Child class. the below would invoke the Child's method() due to run-time polymorphism printing 11
parent p1 = new child();
invokes Child constructor
with the super() call invoke's parent's constructor
Print's "in the parent" and initializes Parent's a to 10
print's in child and initializes Childs a to 11
p1.method();// this invokes Child's method() during run-time
As you are not overriding method() in child class, when the statement,
parent p1 = new child();
is executed, parent version of method() will be executed, and the only a value known to parent class is its own a. hence it will print a=10 (as it is on the stack at that time).
finally, you are just shadowing the variable a from parent class to child class.
When you do this
Parent P1=new Child();
what JVM do is
first Initialize Parent()
||
second Initialize Child()
So , first Parent constructor get called and then child's , but the output value will be 11 , because p1 is referring to child's object.
The issue is you created a child instance and stored it in a reference of the parent. Hence, when your access the object's property, JVM refers to the parent's variable value.
In case, it would have been a child class's reference variables, you would have received the child class' variable value.
The above is a feature of Java.
As you create the Instance of Parent. so in run time the compiler call the parent object ,
try the Below code.
public static void main(String args[]) throws IOException {
child c1 = new child();
c1.method();
}
Related
I have add my question in the comment of the code.
class Parent{
int num =9; //I think num in Parent class is overrided by the num in Child class. why is the num in the first line of output is still 9?
{ //code block
System.out.println("Parent constructor code..."+num);
}
Parent(){
System.out.println("Parent constructor run");
show(); //why does this method here invoke the show() method in Child class?
}
void show() {
System.out.println("Parent show..."+num);
}
}
class Child extends Parent{
int num = 8;
{
System.out.println("Child constructor code..."+num);
num = 10;
}
Child(){
System.out.println("Child constructor run");
show();
}
void show() {
System.out.println("Child show..."+num);
}
}
public class Test {
public static void main(String[] args) {
new Child();
}
}
the output is:
Parent constructor code...9
Parent constructor run
Child show...0
Child constructor code...8
Child constructor run
Child show...10
thank you guys! I have figured out that it's a variable shadowing and hiding problem.
The order of object construction is:
variable declaration and initialization
instance constructor block
constructor
If a class has a parent class, the same order is done for the parent before it is for actual class.
parent first
int num = 9
is evaluated first, num is set to 9 (parent's 1.)
Parent constructor code...9
Instance initializer blocks are executed before a constructor (parent's 2.)
Parent constructor run
The constructor is called (parent's 3.)
Child show...0
The constructor of Parent calls show(). show() is overridden, therefore Child's is called.
Child's 1. and 2. have not been called yet, therefore the overriding num in Child is still 0. *1
then the child
int num = 8
Child's 1. is evaluated
Child constructor code...8
Child's 2. num is set to 10 after this.
Child constructor run
Child's 3.
Child show...10
Child's constructor calling show().
*1:
This is why calling non-final methods in a constructor is very dangerous. Methods tend to rely on a member variable being initialized; they are not at this point.
Were this a non-primitive variable, you might very well run into a NullPointerException if your method tries to access it.
When java creates a child class, it has to call super() to initialize the parent class - this is so it can instantiate private fields in the super class, or other activities. (This does not create an object of the parent class.) That's why you see Parent constructor code...9 - it's calling the parent code, and printing the parent's num.
Because you create a child class, the child's show() is called in the parent constructor. This is why it's dangerous to call non-final methods in a constructor - if a child overrides them, the child's methods will be called instead.
The child's num is 0 because Java initializes member variables to default values, and your code hasn't yet had a chance to set it to 10.
As for your child code, the num is not being overridden, it is being hidden - only methods can be overridden. That's why your child's show() displays it as 10, once it's properly initialized. If you want to access the parent's variable, you can do this with super.num, but this is often regarded as bad practice, since it can cause confusion.
I think it is because automatically your constructor call super class constructor. ( for our first question. ) nevertheless, you override show so when it meets this method, it call the child method
This question already has answers here:
Calling a subclass method from superclass
(5 answers)
Java Inheritance: Why calling a method at the parent constructor level, calls the overridden child method?
(2 answers)
Closed 4 years ago.
Could not access methods from child class using the below line,
Parent p = new Child(); p.print();
Suppose I have a method print() inside Child class and the same method is NOT there in the Parent class. In this scenario we cannot access child class method print() using the above line of code. But note that if we have the same method print() in the parent class then we can access it using the above code.
There might not a real life scenario like this but trying to understand why I am not able to access child class print() using a child object which is of type Parent if we dont have the same method defined in the parent class.
Sample code is below:
public class Main {
public static void main(String[] args)
{
Parent p = new Child();
p.print(); //Compiler throws an error saying "cannot resolve print method".
}
}
class Parent {
int x = 10;
}
class Child extends Parent {
void print(){
System.out.println("Child");
}
int x = 20;
}
More explanation - if I define the print() method inside the parent class then I can access the child class print() method using an object of type Parent. So I assume that we cannot say that an object of type parent can access only members/methods defined inside a parent class.
Also , I know that We can access the child method by casting the parent type to the child type. I am wondering why we cannot access the child class method without casting and if we dont define the same method in the parent class .
I have edited the question so as to make sure that this has no relation with the other question - Calling a subclass method from superclass
When the parent hasn't the method declared (as a concrete or abstract method) the child won't be able to use that method when is instanced inside of a parent variable. You can use the following code sample in order to use it
Parent p = new Child();
if(p instanceof Child){
((Child) p).print();
}
The explanation behind this is that the variable p doesn't actually know what child instance is stored inside it in runtime(there could be several children and none but one have the print() method. Maybe you will know the real type of the object stored in Parent p in compilation time but the execution is another world. So if the p object is an instance of Child, meaning that p is typed as Child or one of its children, you can cast it ((Child) p) and all the methods will be recognized as if a child was (because it is).
Attention, you can cast a class not Casteable and you will have a ClassCastException. In this concrete example writting the if sentence wouldn't be necessary because we are certain about the p type, but some times in runtime things get messy and we don't know what is stored where so ensuring the sanity of your castings becomes esential. Talking about casting variables, if you only want the class Child to access to the method print but not its subclasses you can use
Parent p = new Child();
if(p.getClass() == Child.class){
((Child) p).print();
}
If you don't want to cast the children and your parent class is suitable to have the method print (not allways an option), as you said you can declare it as a concrete method in the parent and override the method in the child)
class Parent {
int x = 10;
void print(){
System.out.println("Parent");
}
}
Or you can declare the method as abstract in the parent and all the children will have to implement it, but then you won't be able to create objects of the parent as long as it will have to be abstract.
abstract class Parent {
int x = 10;
abstract void print();
}
Resuming, if a parent has a child, the child will have all the methods of the parent but as long as is the parent, will have none of the child's methods. A casting will be needed. If the method print is writen in the child and in the parent, the lowest overwritting method will be the one executed (the child one in this case). As an extra, you can use a method implemented in the parent using 'super' (the same that in constructors)
class Child extends Parent {
void print(){
super.print("Child");
}
int x = 20;
}
Parent p = new Child();
you are creating the Parent object with child class. So, it is simple that the Parent object p doesn't have the method print(). But the Child object has the method print(), so if you create a Child object , then you can access the method print() from the Child class.
Here the precedence of methods comes into play. If you have print() method in both classes, then the child class method has the precedence over the parent class method.
NB: The inheritance is unidirectional not bidirectional.
I am studying overriding member functions in Java and thought about experimenting with overriding member variables.
So, I defined classes
public class A{
public int intVal = 1;
public void identifyClass()
{
System.out.println("I am class A");
}
}
public class B extends A
{
public int intVal = 2;
public void identifyClass()
{
System.out.println("I am class B");
}
}
public class mainClass
{
public static void main(String [] args)
{
A a = new A();
B b = new B();
A aRef;
aRef = a;
System.out.println(aRef.intVal);
aRef.identifyClass();
aRef = b;
System.out.println(aRef.intVal);
aRef.identifyClass();
}
}
The output is:
1
I am class A
1
I am class B
I am not able to understand why when aRef is set to b intVal is still of class A?
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.
Variables are not polymorphic in Java; they do not override one another.
There is no polymorphism for fields in Java.
Variables decision happens at a compile time so always Base Class variables (not child’s inherited variables) will be accessed.
So whenever upcasting happens always remember
1) Base Class variables will be accessed.
2) Sub Class methods(overridden methods if overriding happened else inherited methods as it is from parent) will be called.
Variables are resolved compile-time, methods run-time. The aRef is of type A, therefore aRef.Intvalue is compile-time resolved to 1.
OverRiding Concept in Java
Functions will override depends on object type and variables will accessed on reference type.
Override Function: In this case suppose a parent and child class both have same name of function with own definition. But which function will execute it depends on object type not on reference type on run time.
For e.g.:
Parent parent=new Child();
parent.behaviour();
Here parent is a reference of Parent class but holds an object of Child Class so that's why Child class function will be called in that case.
Child child=new Child();
child.behaviour();
Here child holds an object of Child Class, so the Child class function will be called.
Parent parent=new Parent();
parent.behaviour();
Here parent holds the object of Parent Class, so the Parent class function will be called.
Override Variable: Java supports overloaded variables. But actually these are two different variables with same name, one in the parent class and one in the child class. And both variables can be either of the same datatype or different.
When you trying to access the variable, it depends on the reference type object, not the object type.
For e.g.:
Parent parent=new Child();
System.out.println(parent.state);
The reference type is Parent so the Parent class variable is accessed, not the Child class variable.
Child child=new Child();
System.out.println(child.state);
Here the reference type is Child, so the Child class variable is accessed not the Parent class variable.
Parent parent=new Parent();
System.out.println(parent.state);
Here the reference type is Parent, so Parent class variable is accessed.
From JLS Java SE 7 Edition §15.11.1:
This lack of dynamic lookup for field accesses allows programs to be run efficiently with straightforward implementations. The power of late binding and overriding is available, but only when instance methods are used.
Answers from Oliver Charlesworth and Marko Topolnik are correct, I would like to elaborate a little bit more on the why part of the question:
In Java class members are accessed according the type of the reference and not the type of the actual object. For the same reason, if you had a someOtherMethodInB() in class B, you wouldn't be able to access it from aRef after aRef = b is run. Identifiers (ie class, variable, etc names) are resolved at compile time and thus the compiler relies on the reference type to do this.
Now in your example, when running System.out.println(aRef.intVal); it prints the value of intVal defined in A because this is the type of the reference you use to access it. The compiler sees that aRef is of type A and that's the intVal it will access. Don't forget that you have both fields in the instances of B. JLS also has an example similar to yours, "15.11.1-1. Static Binding for Field Access" if you want to take a look.
But why do methods behave differently? The answer is that for methods, Java uses late binding. That means that at compile time, it finds the most suitable method to search for during the runtime. The search involves the case of the method being overridden in some class.
I hope this can help:
public class B extends A {
// public int intVal = 2;
public B() {
super();
super.intVal = 2;
}
public void identifyClass() {
System.out.println("I am class B");
}
}
So overriding variable of base class is not possible, but base class variable value can be set (changed) from constructor of inherited class.
This is called variable hiding. When you assign aRef = b; , aRef has two intVal, 1 is named just intVal another is hidden under A.intVal (see debugger screenshot), Because your variable is of type class A , even when you print just intVal java intelligently picks up A.intVal.
Answer 1: One way of accessing child class's intVal is System.out.println((B)aRef.intVal);
Answer 2: Another way of doing it is Java Reflection because when you use reflection java cant intelligently pickup hidden A.intVal based on Class type, it has to pick up the variable name given as string -
import java.lang.reflect.Field;
class A{
public int intVal = 1;
public void identifyClass()
{
System.out.println("I am class A");
}
}
class B extends A
{
public int intVal = 2;
public void identifyClass()
{
System.out.println("I am class B");
}
}
public class Main
{
public static void main(String [] args) throws Exception
{
A a = new A();
B b = new B();
A aRef;
aRef = a;
System.out.println(aRef.intVal);
aRef.identifyClass();
aRef = b;
Field xField = aRef.getClass().getField("intVal");
System.out.println(xField.get(aRef));
aRef.identifyClass();
}
}
Output -
1
I am class A
2
I am class B
Well, I hope u got the answer. If not, you can try seeing in the debug mode. the subclass B has access to both the intVal. They are not polymorphic hence they are not overriden.
If you use B's reference you will get B's intVal. If you use A's reference , you will get A's intVal. It's that simple.
As per the Java specifications, the instance variables are not overridden from a super class by a sub class when it is extended.
Hence the variable in the sub class only can be seen as one sharing the same name.
Also when the constructor of A is called during the instance creation of B the variable (intVal) is initialized and hence the output.
It is because when you assign b to aRef, it is resolved, leading aRef to just be of class A. This means that aRef does not have access to any of class B's fields or methods. If you call for intVal instead by using b.intVal, you will get 2.
Java has a feather of encapsulation means it tightly binds the property and the behavior of an object. so only via a class reference we can call it's behavior to change it's property.
and in inheritance only method overrides so that it can affects only it's property.
As Many users have already pointed out, this is not polymorphism. Polymorphism only applies to methods(functions).
Now as to why the value of the intVal of class A is printed, this happens because as you can see the reference aRef is of type A.
I can see why you are confused by it. By the same procedure you have accessed the overridden methods for ex. the method identifyClass() but the not the variables which directly proves the first line that I have written .
Now in order to access the variable you can do ((Superclass)c).var
Note here that the Superclass can be many levels up for example
A<-B<-C. That is C extends B and B extends A. If you wanted the value of var of A then you could have done ((A)c).var .
EDIT: as one of the users have pointed out this 'trick' does not apply to static methods, because they are static.
This question already has answers here:
Superclass reference not able to call subclass method in Java
(2 answers)
Closed 6 years ago.
Consider, for example, the following code
class Main {
public static void main(String[] args) {
Parent obj = new Child();
obj.firstMethod(); // Prints >> from child Class (polymorphism, great!)
obj.secondMethod(); // why this call fails?
// the obj variable reference a Child object
// which has secondMethod!
}
static class Parent {
Parent() {}
void firstMethod () {
System.out.println("from Parent Class");
}
}
static class Child extends Parent {
Child() {}
#Override
void firstMethod () {
System.out.println("from child Class");
}
void secondMethod () {
//
}
}
}
So obj variable is just a reference of type Parent, and the actual object the reference is pointing to is of type Child. I can't understand why such access fails!
Because the declared type Parent doesn't contain the method : void secondMethod ().
So, the compilation fails.
The polymorphism works only if both classes (Parent and Child) have a common method which comes from the parent class and that the child class overrides as in your firstMethod() example.
In your case, you call a method specific to the child class, so you should declare
Child obj = new Child() or do a cast to Child when you call secondMethod().
Don't forget that Polymorphism allows variables to have a dynamic behavior by using at runtime the implementation of the effective instance behind the variable. It is therefore meaningful only if the classes share a same operation.
The language spec answer: refer to JLS Sec 15.12. Emphasis added.
15.12.1. Compile-Time Step 1: Determine Class or Interface to Search
The first step in processing a method invocation at compile time is to figure out the name of the method to be invoked and which class or interface to search for definitions of methods of that name.
...
For the class or interface to search, there are six cases to consider, depending on the form that precedes the left parenthesis of the MethodInvocation:
...
If the form is ExpressionName . [TypeArguments] Identifier, then the class or interface to search is the declared type T of the variable denoted by ExpressionName if T is a class or interface type, or the upper bound of T if T is a type variable.
15.12.2. Compile-Time Step 2: Determine Method Signature
The second step searches the type determined in the previous step for member methods.
In obj.secondMethod();, ExpressionName is obj, which has declared type Parent. As such, the declared type T is Parent, not Child, so only methods in Parent are searched for. There's no method in Parent called secondMethod, so it's a compile-time error.
I am studying overriding member functions in Java and thought about experimenting with overriding member variables.
So, I defined classes
public class A{
public int intVal = 1;
public void identifyClass()
{
System.out.println("I am class A");
}
}
public class B extends A
{
public int intVal = 2;
public void identifyClass()
{
System.out.println("I am class B");
}
}
public class mainClass
{
public static void main(String [] args)
{
A a = new A();
B b = new B();
A aRef;
aRef = a;
System.out.println(aRef.intVal);
aRef.identifyClass();
aRef = b;
System.out.println(aRef.intVal);
aRef.identifyClass();
}
}
The output is:
1
I am class A
1
I am class B
I am not able to understand why when aRef is set to b intVal is still of class A?
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.
Variables are not polymorphic in Java; they do not override one another.
There is no polymorphism for fields in Java.
Variables decision happens at a compile time so always Base Class variables (not child’s inherited variables) will be accessed.
So whenever upcasting happens always remember
1) Base Class variables will be accessed.
2) Sub Class methods(overridden methods if overriding happened else inherited methods as it is from parent) will be called.
Variables are resolved compile-time, methods run-time. The aRef is of type A, therefore aRef.Intvalue is compile-time resolved to 1.
OverRiding Concept in Java
Functions will override depends on object type and variables will accessed on reference type.
Override Function: In this case suppose a parent and child class both have same name of function with own definition. But which function will execute it depends on object type not on reference type on run time.
For e.g.:
Parent parent=new Child();
parent.behaviour();
Here parent is a reference of Parent class but holds an object of Child Class so that's why Child class function will be called in that case.
Child child=new Child();
child.behaviour();
Here child holds an object of Child Class, so the Child class function will be called.
Parent parent=new Parent();
parent.behaviour();
Here parent holds the object of Parent Class, so the Parent class function will be called.
Override Variable: Java supports overloaded variables. But actually these are two different variables with same name, one in the parent class and one in the child class. And both variables can be either of the same datatype or different.
When you trying to access the variable, it depends on the reference type object, not the object type.
For e.g.:
Parent parent=new Child();
System.out.println(parent.state);
The reference type is Parent so the Parent class variable is accessed, not the Child class variable.
Child child=new Child();
System.out.println(child.state);
Here the reference type is Child, so the Child class variable is accessed not the Parent class variable.
Parent parent=new Parent();
System.out.println(parent.state);
Here the reference type is Parent, so Parent class variable is accessed.
From JLS Java SE 7 Edition §15.11.1:
This lack of dynamic lookup for field accesses allows programs to be run efficiently with straightforward implementations. The power of late binding and overriding is available, but only when instance methods are used.
Answers from Oliver Charlesworth and Marko Topolnik are correct, I would like to elaborate a little bit more on the why part of the question:
In Java class members are accessed according the type of the reference and not the type of the actual object. For the same reason, if you had a someOtherMethodInB() in class B, you wouldn't be able to access it from aRef after aRef = b is run. Identifiers (ie class, variable, etc names) are resolved at compile time and thus the compiler relies on the reference type to do this.
Now in your example, when running System.out.println(aRef.intVal); it prints the value of intVal defined in A because this is the type of the reference you use to access it. The compiler sees that aRef is of type A and that's the intVal it will access. Don't forget that you have both fields in the instances of B. JLS also has an example similar to yours, "15.11.1-1. Static Binding for Field Access" if you want to take a look.
But why do methods behave differently? The answer is that for methods, Java uses late binding. That means that at compile time, it finds the most suitable method to search for during the runtime. The search involves the case of the method being overridden in some class.
I hope this can help:
public class B extends A {
// public int intVal = 2;
public B() {
super();
super.intVal = 2;
}
public void identifyClass() {
System.out.println("I am class B");
}
}
So overriding variable of base class is not possible, but base class variable value can be set (changed) from constructor of inherited class.
This is called variable hiding. When you assign aRef = b; , aRef has two intVal, 1 is named just intVal another is hidden under A.intVal (see debugger screenshot), Because your variable is of type class A , even when you print just intVal java intelligently picks up A.intVal.
Answer 1: One way of accessing child class's intVal is System.out.println((B)aRef.intVal);
Answer 2: Another way of doing it is Java Reflection because when you use reflection java cant intelligently pickup hidden A.intVal based on Class type, it has to pick up the variable name given as string -
import java.lang.reflect.Field;
class A{
public int intVal = 1;
public void identifyClass()
{
System.out.println("I am class A");
}
}
class B extends A
{
public int intVal = 2;
public void identifyClass()
{
System.out.println("I am class B");
}
}
public class Main
{
public static void main(String [] args) throws Exception
{
A a = new A();
B b = new B();
A aRef;
aRef = a;
System.out.println(aRef.intVal);
aRef.identifyClass();
aRef = b;
Field xField = aRef.getClass().getField("intVal");
System.out.println(xField.get(aRef));
aRef.identifyClass();
}
}
Output -
1
I am class A
2
I am class B
Well, I hope u got the answer. If not, you can try seeing in the debug mode. the subclass B has access to both the intVal. They are not polymorphic hence they are not overriden.
If you use B's reference you will get B's intVal. If you use A's reference , you will get A's intVal. It's that simple.
As per the Java specifications, the instance variables are not overridden from a super class by a sub class when it is extended.
Hence the variable in the sub class only can be seen as one sharing the same name.
Also when the constructor of A is called during the instance creation of B the variable (intVal) is initialized and hence the output.
It is because when you assign b to aRef, it is resolved, leading aRef to just be of class A. This means that aRef does not have access to any of class B's fields or methods. If you call for intVal instead by using b.intVal, you will get 2.
Java has a feather of encapsulation means it tightly binds the property and the behavior of an object. so only via a class reference we can call it's behavior to change it's property.
and in inheritance only method overrides so that it can affects only it's property.
As Many users have already pointed out, this is not polymorphism. Polymorphism only applies to methods(functions).
Now as to why the value of the intVal of class A is printed, this happens because as you can see the reference aRef is of type A.
I can see why you are confused by it. By the same procedure you have accessed the overridden methods for ex. the method identifyClass() but the not the variables which directly proves the first line that I have written .
Now in order to access the variable you can do ((Superclass)c).var
Note here that the Superclass can be many levels up for example
A<-B<-C. That is C extends B and B extends A. If you wanted the value of var of A then you could have done ((A)c).var .
EDIT: as one of the users have pointed out this 'trick' does not apply to static methods, because they are static.