Why do we assign a parent reference to the child object in Java?
First, a clarification of terminology: we are assigning a Child
object to a variable of type Parent
. Parent
is a reference to an object that happens to be a subtype of Parent
, a Child
.
It is only useful in a more complicated example. Imagine you add getEmployeeDetails
to the class Parent:
public String getEmployeeDetails() {
return "Name: " + name;
}
We could override that method in Child
to provide more details:
@Override
public String getEmployeeDetails() {
return "Name: " + name + " Salary: " + salary;
}
Now you can write one line of code that gets whatever details are available, whether the object is a Parent
or Child
:
parent.getEmployeeDetails();
The following code:
Parent parent = new Parent();
parent.name = 1;
Child child = new Child();
child.name = 2;
child.salary = 2000;
Parent[] employees = new Parent[] { parent, child };
for (Parent employee : employees) {
employee.getEmployeeDetails();
}
Will result in the output:
Name: 1
Name: 2 Salary: 2000
We used a Child
as a Parent
. It had specialized behavior unique to the Child
class, but when we called getEmployeeDetails()
we could ignore the difference and focus on how Parent
and Child
are similar. This is called subtype polymorphism.
Your updated question asks why Child.salary
is not accessible when the Child
object is stored in a Parent
reference. The answer is the intersection of "polymorphism" and "static typing". Because Java is statically typed at compile time you get certain guarantees from the compiler but you are forced to follow rules in exchange or the code won't compile. Here, the relevant guarantee is that every instance of a subtype (e.g. Child
) can be used as an instance of its supertype (e.g. Parent
). For instance, you are guaranteed that when you access employee.getEmployeeDetails
or employee.name
the method or field is defined on any non-null object that could be assigned to a variable employee
of type Parent
. To make this guarantee, the compiler considers only that static type (basically, the type of the variable reference, Parent
) when deciding what you can access. So you cannot access any members that are defined on the runtime type of the object, Child
.
When you truly want to use a Child
as a Parent
this is an easy restriction to live with and your code will be usable for Parent
and all its subtypes. When that is not acceptable, make the type of the reference Child
.
Polymorphism in java: Why do we set parent reference to child object?
Okay. I think I got my answer.
public class Polymorphism {
public static void main(String[] args){
Animal obj1 = new Horse();
Horse obj2 = new Horse();
obj1.shout(); //output is neigh..
obj2.shout(); //output is neigh..
obj1.winRaces(); /*But this is not allowed and throws compile time error,
even though the object is of Animal type.*/
}
}
class Animal{
public void shout(){
System.out.println("Parent animal's shout");
}
}
class Horse extends Animal{
public void shout(){
System.out.println("neigh..");
}
public void winRaces(){
System.out.println("won race..");
}
}
So, when we use parent reference for child class object, we cannot access any specific methods in child class (that are not present in parent class) using that object.
Why parent object cannot be assigned to a child reference in java?
As user7 said and Stultuske updated, a Car
is a Vehicle
, but not all Vehicles
are Car
s. So this:
Vehicle v = /*...some kind of Vehicle...*/;
Car c = v;
...makes no sense. What if v
doesn't refer to a Car
instance?
More formally, it would violate the contract. Say we have:
class Vehicle {
}
class Car extends Vehicle {
public void drive() {
// ...
}
}
Suppose this actually worked:
Car c = new Vehicle(); // Doesn't work, but let's pretend it does
What should happen if you call c.drive()
? The contract (Car
) says it has a drive
method, but the object (of type Vehicle
) does not.
Even if Car
didn't add any (public) features, it's still misleading to have a Car
-typed variable (which, by definition, refers to Car
instances or instances of a Car
subclass) refer to a Vehicle
object. The Vehicle
isn't (necessarily) a Car
.
If you have a Vehicle
reference to an object and you know the object is actually a Car
, then you can cast it:
Vehicle v = new Car();
Car c = (Car)v;
...since there's no mismatch there; the object actually is a Car
. The cast tells the compiler you, the programmer, are taking responsibility for the object that v
refers to actually being compatible with Car
. (And the JVM checks at runtime, so if you're wrong, you get a ClassCastException
.)
Accessing child properties from parent type reference in java
Here when you write Parent p = new Child()
, then object of child class is created with properties of both Parent and Child class but the reference variable which is used to hold this object is of Parent type or you can say of Parent class.
When we want to access the instance methods or variables of any class, then the reference variable should be of that class only or its child class.
So we cannot access variable of child class with the reference variable of parent class.
Only the variables present in the Parent class can be accessed through the reference variable of parent class, doesn't matter you are using that reference variable to hold parent Class object or Child class object.
So only way to access 'a' instance variable in the code from p reference variable is to typecast p to Child type and then it can access variables of Child class.
`
Parent p = new Child();
System.out.println(((Child)p).a);
`
Why can't reference to child Class object refer to the parent Class object?
Exactly because aChild is a superset of aParent's abilities. You can write:
class Fox : Animal
Because each Fox is an Animal. But the other way is not always true (not every Animal is a Fox).
Also it seems that you have your OOP mixed up. This is not a Parent-Child relationship, because there's no composition/trees involved. This is a Ancestor/Descendant inheritance relation.
Inheritance is "type of" not "contains". Hence it's Fox is a type of Animal, in your case it doesn't sound right -- "Child is a type of Parent" ? The naming of classes was the source of confusion ;).
class Animal {}
class Fox : Animal {}
class Fish : Animal {}
Animal a = new Fox(); // ok!
Animal b = new Fish(); // ok!
Fox f = b; // obviously no!
Related Topics
How to Change the Dock Icon of a Java Program
Prevent SQL Injection Attacks in a Java Program
Running Multiple Launch Configurations at Once
Create a New Line in Java's Filewriter
How to Convert Current Date into String in Java
What Is the Fastest Way to Compare Two Sets in Java
Does Calling Clone() on an Array Also Clone Its Contents
How Does Java's System.Exit() Work with Try/Catch/Finally Blocks
Hibernate - @Elementcollection - Strange Delete/Insert Behavior
Instantiating Object of Type Parameter
Httpurlconnection Invalid Http Method: Patch
Converting Characters to Integers in Java
Why to Use Stringbuffer in Java Instead of the String Concatenation Operator