When instantiating a (sub)Class, is there any diff

2020-07-27 05:54发布

问题:

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:

  1. ChildClass obj1 = new ChildClass(5)
  2. 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 ?

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

  • If they have the same methods just that the child implements the abstract method then there isn't any difference.
  • If you have added aditional methods the the child then thoose won't be accessible if you declare it as a parent.


回答5:

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.

    }
}


回答6:

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.