Say I have a Class called ParentClass
and a Class called ChildClass
The ParentClass
is abstract and the ChildClass
extends the ParentClass
per Java terminology. Furthermore, the ParentClass
has a constructor which takes an int
as a parameter. Now in another class I want to instantiate the ChildClass
. I have tried the two below ways:
ChildClass obj1 = new ChildClass(5)
ParentClass obj2 = new ChildClass(5)
Java allows me to use any of the two above ways. My question is, is there actually any difference? Can I use the two, interchangeably if I want to ?
Both work, and both create the same object in memory. But only the first one will allow you to use ChildClass additional specific properties or methods the ParentClass doesn't know about.
Example :
abstract class ParentClass{
...
}
class ChildClass extends ParentClass {
public void SomeChildMethod(){ ... }
...
}
...
ChildClass obj1 = new ChildClass(5);
ParentClass obj2 = new ChildClass(5);
obj1.SomeChildMethod(); // ok
obj2.SomeChildMethod(); // compilation error
((ChildClass)obj2).SomeChildMethod(); // ok
So, use the second instantiation method only if you're sure you'll never need the specific child methods or properties, if any.
The created object is effectively the same.
The first method allows you to use methods defined in the ChildClass
and not in ParentClass
. So
obj1.aMethodNotInParentClass();
compiles while
obj2.aMethodNotInParentClass();
does not.
Alternatively, using the second form allows you to replace the inner class with other implementation more easily. If you want to use AnotherChildClass
instead of ChildClass
,
ParentClass obj2 = new AnotherChildClass(5);
is all the change you need to do (assuming classes are properly defined); using the first method will probably need some changes in other places of your code.
As a rule of thumb, define the variables as the more general class that defines(*) all the methods you need of the object. So, if you use any method of ChildClass
that is not defined in ParentClass
, use the first way, otherwise, use the second.
(*) Note that I mention definition, not implementation. If you override a method in ChildClass
, you will use that implementation because the object created is of that class.
In memory the exact same object will be used. However, you can only use the variable obj2
as if it contained a ParentClass
object without taking for granted all the nice functionality of your ChildClass
class. If ChildClass
declares a method f()
, but ParentClass
does not, the call obj2.f()
will not work - although the object in memory could be able to run the method perfectly well.
The second alternative will only allow to use methods declared in the ParentClass. For example:
public class ParentClass {
public void doX() {}
}
public class ChildClass {
public void doY() {}
public static void main() {
ParentClass p = new ChildClass();
ChildClass c = new ChildClass();
p.doX(); //works
c.doX(); //works
p.doY(); //not allowed
c.doY(); //works
((ChildClass) p).doY(); //this way you cast the object to ChilClass and can use its methods.
}
}
Yes there is a difference.
The first way uses dynamic binding to give you a child instance as a parent object. This only gives you the functionality of the parent object onto the child instance.
The second way will give you an instance of the child object as the child object, allowing you to use all of its methods and its parent objects methods rather than being limited to the methods of the parent class.