为什么我们要在 Java 中为子对象分配父引用?

2022-08-31 09:48:53

我问了一个非常简单的问题,但我对此有点困惑。

假设我有一个类:Parent

public class Parent {

    int name;
}

并有另一个类:Child

public class Child extends Parent{

    int salary;
}

最后是我的主要.java类

public class Main {

    public static void main(String[] args)
    {
        Parent parent = new Child();
        parent.name= "abcd";
    }
}

如果我使一个子对象像

Child child = new Child():

然后对象可以访问这两个变量。childname and salary

我的问题是:

Parent parent = new Child();

仅提供父类的变量的访问权限。那么这条线的确切用途是什么??name

 Parent parent = new Child();

而且,当它使用动态多态性时,为什么子类的变量在执行此操作后无法访问

Parent parent = new Child();

答案 1

首先,对术语的澄清:我们将一个对象分配给类型为 的变量。 是对碰巧是 的子类型的对象的引用。ChildParentParentParentChild

它仅在更复杂的示例中有用。想象一下,您添加到类父级:getEmployeeDetails

public String getEmployeeDetails() {
    return "Name: " + name;
}

我们可以重写该方法以提供更多详细信息:Child

@Override
public String getEmployeeDetails() {
    return "Name: " + name + " Salary: " + salary;
}

现在,您可以编写一行代码来获取任何可用的详细信息,无论对象是 a 还是 :ParentChild

parent.getEmployeeDetails();

下面的代码:

Parent parent = new Parent();
parent.name = 1;
Child child = new Child();
child.name = 2;
child.salary = 2000;
Parent[] employees = new Parent[] { parent, child };
for (Parent employee : employees) {
    employee.getEmployeeDetails();
}

将产生以下结果:

Name: 1
Name: 2 Salary: 2000

我们使用 a 作为 .它具有该类独有的特殊行为,但是当我们调用时,我们可以忽略差异并专注于如何和相似。这称为亚型多态性ChildParentChildgetEmployeeDetails()ParentChild

更新后的问题询问了当对象存储在引用中时,为什么无法访问该对象。答案是“多态性”和“静态类型”的交集。因为Java在编译时是静态类型的,所以你从编译器那里得到了某些保证,但你被迫遵循规则作为交换,否则代码将无法编译。在这里,相关的保证是子类型的每个实例(例如)都可以用作其超类型的实例(例如)。例如,可以保证,当您访问或定义方法或字段时,可以保证在任何非空对象上定义方法或字段,这些对象可以分配给类型的变量。为了保证这一点,编译器在决定可以访问的内容时只考虑该静态类型(基本上是变量引用的类型)。因此,您无法访问在对象的运行时类型 上定义的任何成员。Child.salaryChildParentChildParentemployee.getEmployeeDetailsemployee.nameemployeeParentParentChild

当你真的想使用a作为一个,这是一个容易接受的限制,你的代码将可用于及其所有子类型。如果这是不可接受的,请创建引用的类型。ChildParentParentChild


答案 2

编译程序时,基类的引用变量获取内存,编译器检查该类中的所有方法。因此,它检查所有基类方法,但不检查子类方法。现在,在创建对象的运行时,只有选中的方法可以运行。在函数运行的子类中重写某个方法的情况下。子类其他函数不会运行,因为编译器在编译时尚未识别它们。