【问题标题】:Understanding Java's inheritance model理解Java的继承模型
【发布时间】:2015-09-07 06:29:35
【问题描述】:

示例代码:

public class Parent {
  String name = "Parent";

  public String getName() {
    return this.name;
  }
}

public class Child extends Parent {
  String name = "Child";

  public String getName() {
    return this.name;
  }
}

public class Tester {
  public static void main (String[] args) {
    Parent p = new Child();
    Child  c = new Child();
    System.out.println("p.name is " + p.name); // prints out "Parent"
    System.out.println("c.name is " + c.name); // prints out "Child"
    System.out.println("p.getName() is " + p.getName()); // prints out "Child"
    System.out.println("c.getName() is " + c.getName()); // prints out "Child"
  }
}

我目前的理解

到目前为止,我对 Java 继承的理解让我理解了为什么第三和第四个 println 语句会产生“Child”作为输出。在编译时,编译器确保 getName 方法在引用变量的类型中定义,但在运行时确定哪个版本 getName。由于两个引用变量实际上都引用了一个Child 对象,因此调用了 Child 的getName

问题 1

但是,为什么当你直接访问实例变量时,行为与访问方法的方式不同呢?特别是,p.name 返回的是“Parent”而不是“Child”,这让我感到很奇怪。

问题 2

类似地,如果我在 Child 类中注释掉 getName 函数并重新运行 Tester 中的代码,我会惊讶地看到 p.getName()c.getName() 返回 "父”而不是“子”。

有人可以帮忙详细说明这两个问题吗?

【问题讨论】:

  • 您所遇到的整个问题是您认为您也可以覆盖变量,但您不能。检查this
  • 感谢@KevinEsche 分享此链接!这如何适用于我的第二个问题?
  • 此外,继承描述了一个 is a 关系。出于这个原因,Parent / Child 的类比非常糟糕。 Child 不是 Parent
  • @wmock,因为同名的变量不会使它们在逻辑上连接。函数 get name 不会查找名称为 name 的变量。它具体指的是它在定义方法的类中找到的 on(或者它在可见性范围内继承的任何类)
  • 你了解静态类型和运行时类型的区别吗? (p 有静态类型Parent 和运行时类型Childc 有静态类型Child 和运行时类型Chald。)编译器 决定了哪个字段访问,即字段访问取决于静态类型。 (如果你查看编译后的字节码,p.name 将引用Parent.name。)VM 决定调用哪个方法,即方法访问取决于运行时类型。

标签: java inheritance


【解决方案1】:

在 Java 中不能覆盖变量。你所做的叫做隐藏变量(Parent中的变量name很难访问)

理解您所描述的行为的方法是将name 仅视为变量的名称,而不是实际变量。在Parent 的上下文中使用时(就代码而言,不是变量的实际类型),它指向的变量与在Child 的上下文中使用时不同。

当调用c.namep.name 时,您告诉程序使用哪个上下文,因为变量cp 分别声明为ChildParent 类型。在类内部的方法中使用它时,将使用当前类的变量。

如果你想在子类中使用Parent.name,你必须强制转换它:

System.out.println("c.name is " + ((Parent) c).name);

对于方法,调用的函数始终是被调用变量的实际类型。在您的情况下,无论从TesterParentClient 调用它。

当然最好不要隐藏变量,对不同的变量使用不同的名称。

【讨论】:

  • 感谢@Thirler 的澄清 - 现在这对我来说很有意义。
猜你喜欢
  • 2014-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多