Why is it allowed for a parent class object to be instantiated using a child class's constructor?
That's not what's happening there. In this line:
parent p = new child();
...you're creating a child
object, not a parent
object. The variable you're using to refer to it, p
, has the type parent
, which means that you can only use parent
stuff via that reference, but the object is a child
object. The object does have a y
, you just can't access it via p
. You can see that by doing this:
parent p = new child();
System.out.println( ((child)p).y );
By telling the compiler we know that p
refers to child
even though it's of type parent
(via a "cast"), we can access the child
-specific parts of it. (This is not good practice when you have an alternative.)
This ability for there to be a difference (within constraints) between the reference you have to something and what it actually is is called "polymorphism" (taking multiple forms) and is central to object-oriented programming.
Consider:
class Animal {
}
class Dog extends Animal {
}
class Cat extends Animal {
}
All Dog
s are Animal
s, as are all Cat
s, but Dog
s are not Cat
s. Suppose you run a pet shop and want to store a list of the animals you have on hand:
List<Animal> animals;
The entries can be objects of type Animal
or any of its subtypes, such as Dog
and Cat
. This lets you have common aspects of animals on Animal
, and then only Dog
- or Cat
- specific aspects (properties or behaviors) on those types. You can run through your list of Animal
s acting on their animal-ness without worrying about whether they're Dog
s or Cat
s.