【问题标题】:Why is it allowed for a parent class object to be instantiated using a child class's constructor?为什么允许使用子类的构造函数来实例化父类对象?
【发布时间】:2015-12-22 04:35:57
【问题描述】:

考虑以下几点:

public class parent {
    int x;

    parent() {
        x = 5;
    }

}

public class child extends parent {
int y;

child() {
    super();
    y = 10;
}

public static void main(String[] args) {

    parent p = new child();
    System.out.println(p.y);//can't access variable y
}

}

这里子类的构造函数被父类的对象调用。我在做Android编程时遇到过很多次这种情况。 我的问题是为什么允许这样做?子类的构造函数可能会初始化其他成员,但它们的蓝图可能不会像上述情况那样在父类中定义。

【问题讨论】:

  • 提示:对象p 类型及其基本类型是什么?下一个 ychild 类中声明。
  • "这里子类的构造函数被父类的对象调用。" - 不,您定义了一个 child 类型的对象,但您的其余代码将其视为 parent 的对象。
  • 希望您有一本字典,您可以在其中查找“扩展”。在这种情况下(child extends parent),它意味着子类拥有父类的所有内容,以及它自己的一些字段和方法。
  • 注意:在 Java 中,overwhelming 约定是将类名大写,例如Parent,不是parent,和Child,不是child。您不必在自己的代码中遵循约定,但它很有用,并且在与他人共享代码时(例如,在提问时)遵循约定非常有用。 :-)

标签: java oop object inheritance


【解决方案1】:

为什么允许使用子类的构造函数来实例化父类对象?

那不是那里发生的事情。在这一行:

parent p = new child();

...您正在创建 child 对象,而不是 parent 对象。您用来引用它的变量p 具有parent 类型,这意味着您只能通过该引用使用parent 东西,但对象是child 对象。对象确实有一个y,你只是不能通过p 访问它。你可以这样做:

parent p = new child();
System.out.println( ((child)p).y );

通过告诉编译器我们知道p 指的是child,即使它是parent 类型(通过“强制转换”),我们可以访问它的child 特定部分。 (当您有替代方案时,这不是一个好习惯。)

在您对某事物的引用与实际引用之间存在差异(在约束范围内)的这种能力称为“多态性”(采用多种形式),是面向对象编程的核心。

考虑:

class Animal {
}

class Dog extends Animal {
}

class Cat extends Animal {
}

所有Dogs 和Cats 都是Animals,但Dogs 不是Cats。假设您经营一家宠物店,并且想要存储您手头上的动物列表:

List<Animal> animals;

条目可以是Animal 类型的对象或其任何子类型,例如DogCat。这使您可以在Animal 上拥有动物的共同方面,然后在这些类型上只有Dog- 或Cat- 特定方面(属性或行为)。您可以浏览您的 Animals 列表,根据他们的动物性行事,而不必担心他们是 Dogs 还是 Cats。

【讨论】:

    【解决方案2】:

    因为孩子也是父母。所以它可以获取它的类型。但是,对象将是一个孩子。所以是 Parent 类型的 Child 对象。

    注意:类名是大写的。

    【讨论】:

      【解决方案3】:

      除了作为构造函数中child 实例化的一部分之外,没有进行父类的实例化。你在这里得到一个实例,它是 child 的一个实例。

      允许分配给parent p,因为每个child 对象也是parent 对象。

      child 对象分配给具有其父级类型的变量使您能够对类的接口进行编程,从而将child 类的使用限制在其父级的方法中。这使您可以灵活地在以后更改实现:

      Parent p = new OtherChild();
      

      这样使用p的代码不需要知道它正在访问ChildOtherChild对象。

      【讨论】:

        【解决方案4】:

        当你写parent p = new child(); 时,它实际上是创建子类的对象。调用子类构造函数时,先调用super()调用超类构造函数。

        【讨论】:

          猜你喜欢
          • 2013-06-08
          • 2012-10-01
          • 1970-01-01
          • 2013-05-05
          • 1970-01-01
          • 2021-08-17
          • 2015-04-24
          • 2017-12-08
          • 2018-09-10
          相关资源
          最近更新 更多