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!
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
.
Why do we assign child class object to parent class reference variable?
It's because you've redeclared the Print
method in Child
. So at compile time, P.Print()
resolves to Parent.Print
, but C.Print()
resolves to Child.Print()
. If you had a virtual method which was overridden in Child
instead, they'd both print "Child Method":
public class Parent
{
// Declare this as virtual, allowing it to be overridden in
// derived classes. The implementation will depend on the
// execution-time type of the object it's called on.
public virtual void Print()
{
Console.WriteLine ("Parent Method");
}
}
public class Child : Parent
{
// Override Parent.Print, so if Print is called on a reference
// with compile-time type of Parent, but at execution it
// refers to a Child, this implementation will be executed.
public override void Print()
{
Console.WriteLine ("Child Method");
}
}
Related:
- What's the difference between
override
andnew
? (C# FAQ entry on MSDN - turns out to have been written by me, but I'd forgotten!) - Knowing when to use the
override
andnew
keywords (MSDN)
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
.)
Why can't object refer to parent object and child object?
All your constructors require the parent and child to be constructed before the current object can be constructed. That is impossible in your case as the references form a dependency cycle (First
-> Fourth
-> Third
-> Second
-> First
, therefore First
can't be fully created till after First
is created, etc.).
One solution would be to make the Node
abstract (or an interface) and only fetch the values when they are requested (i.e. in the getters):
interface Node {
val number: Int
val parent: Node?
val child: Node?
}
object First : Node {
override val number = 1
override val parent get() = Fourth
override val child get() = Second
}
// Similar for Second, Third, and Fourth
If you're interested in why you got that particular pattern of nulls, it's important to remember that objects in Kotlin usually aren't created till the first time they are used.
- The first object you use (in
main
) isFirst
, so it's constructor is called. - The first* thing its constructor does is get a reference to
Fourth
, which in turn doesThird
, which in turn doesSecond
, which in turn tries to doFirst
, butFirst
is already in the process of being created, so its reference isnull
. - Then (we're still in
Second
) it tries to createThird
(as thechild
), which is in the process of being created, so its reference is alsonull
. At this pointSecond
is done, so any future reference to it will not benull
. Third
now has a valid reference toSecond
, and moves on to trying to createFourth
, which is still being created, thusnull
. NowThird
is done.Fourth
now has a valid reference toThird
, and moves on toFirst
, which is still being created, thusnull
. NowForth
is done.First
now has a valid reference toFourth
, and moves on toSecond
, which already exists and is valid. NowFirst
is done.
*Technically the second, since the first thing it does is set the number, but it's the first thing that matters for the purposes of this discussion.
Why we can't instantiate child class object from parent class
Because the compiler automatically casts the deriving class to the base class - it just interprets it as an object of the base class, ignoring other properties. But to cast an object to the derived class, it must have been an object of this derived class before and the compiler wants you to explicitly define the cast. But even if you'd define the cast explicitly, it wouldn't work because the object has never been of the derived type.
Related Topics
How to Get the Selected Item of a Combo Box to a String Variable in C#
Why Is ASP.NET Identity Identitydbcontext a Black-Box
Writing File to Web Server - ASP.NET
How to Remove Specific Style Tag in HTML Using C#
How to Write My C++ Function So I Can Call It from C#
JavaScript Serialization of Datetime in ASP.NET Is Not Giving a JavaScript Date Object
JSON Serialize List<Keyvaluepair<String, Object>>
How to Convert Style Text to C# Object Such as Class/Hashtable/Collection
How to Determine The Screen Width/Height Using C#
Solving a Timeout Error for SQL Query
C#: Throwing Custom Exception Best Practices
Finding the Concrete Type Behind an Interface Instance