说我有一个名为类ParentClass
和一个叫做类ChildClass
在ParentClass
是抽象的和ChildClass
扩展ParentClass
按Java的术语。 此外, ParentClass
具有一个构造,其需要一个int
作为参数。 现在,在另一个类我想实例化ChildClass
。 我已经尝试了两种方式如下:
-
ChildClass obj1 = new ChildClass(5)
-
ParentClass obj2 = new ChildClass(5)
Java允许我使用任何上述两种方式。 我的问题是,是否有任何实际的区别? 我可以用两个,交替如果我想?
无论工作,都在内存中创建相同的对象。 但是,只有第一个将允许您使用ChildClass的父类不知道其他特定属性或方法。
例如:
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
因此,只使用,如果你相信你会永远需要儿童的具体方法或属性,如果有第二个实例方法。
创建的对象实际上是一样的。
第一种方法允许您使用在定义的方法ChildClass
,而不是在ParentClass
。 所以
obj1.aMethodNotInParentClass();
而编译
obj2.aMethodNotInParentClass();
才不是。
另外,使用第二种形式让你更方便地更换与其他实施内部类。 如果你想使用AnotherChildClass
代替ChildClass
,
ParentClass obj2 = new AnotherChildClass(5);
是你需要做的(假设类正确定义)的所有变化; 使用第一种方法可能需要在代码中的其他地方的一些变化。
作为一个经验法则,确定你所需要的对象的变量定义(*)更一般的类的所有方法。 所以,如果你使用的任何方法ChildClass
未在定义ParentClass
中,使用第一种方式,否则,使用第二个。
(*)请注意,我提到的定义 ,而不是实现 。 如果替换的方法ChildClass
,您将使用实现,因为创建的对象是类的。
在存储器中的完全相同的对象将被使用。 但是,你只能使用变量obj2
,如果它包含一个ParentClass
对象,而理所当然所有的好的功能ChildClass
类。 如果ChildClass
声明的方法f()
但ParentClass
没有,通话obj2.f()
将无法正常工作-虽然在内存中的对象可以是能够运行的方法非常清楚。
第二种方案将只允许使用在父类中声明的方法。 例如:
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.
}
}
是,有一点不同。 第一种方式使用动态绑定来给你一个子实例的父对象。 这只是给你的父对象到子实例的功能。 第二种方法会给你的孩子对象作为子对象的实例,让你使用它的全部方法和其父对象的方法,而不是仅限于父类的方法。
文章来源: When instantiating a (sub)Class, is there any difference in what “type” you declare the object as?