【问题标题】:Java wider object assignment conversionJava 更广泛的对象赋值转换
【发布时间】:2014-09-13 09:18:58
【问题描述】:

在下面的例子中,我不明白为什么Base b1 = new Derived(); System.out.println(b1); 会打印出x=10, z=20。我的理解是,由于b1 有一个静态类型的Base,它无权访问Derived 中的字段,所以z 不应该被打印出来。有人可以帮忙解释一下吗?非常感谢!

class Base {
  int x;
  public Base1() { x = 10; }
  public Base1(int x) { this.x =x; }
  public String toString() {
     return "x=" + x ;
  } 
 }
 class Derived1 extends Base1 {
     int z = x * 2;
     public Derived1() {}
     public Derived1(int x, int z) {
        super(x);
        this.z = this.z + z;
     }
     public String toString() {
        return "x=" + x + ", z=" + z;
     }
  }

【问题讨论】:

标签: java casting reference field typing


【解决方案1】:

对象Derived,而不是Base。从b1 到对象的接口BaseBasetoString,所以你可以访问toString。您访问的实现是对象拥有的实现,由Derived 提供,它使用zDerived#toString 的实现可以访问 z,因为它对对象的引用是通过 Derived 引用 (this),而不是 Base 引用。

正如 Oli 在评论中指出的那样,这是多态性的基础——让对象的行为取决于对象而不是对象的接口。

如果对象的内部结构是由我们必须的接口决定的,那么我们在尝试实现interfaces 时会遇到一些麻烦! :-)

【讨论】:

  • 谢谢!我仍然有点困惑,因为我记得老师说过这样的话:“这个更广泛的作业是可以的,但是 b1 将无法访问 Derived 中的字段。”那么这是指什么呢?是不是说它可以像你说的那样通过方法访问z,但是不能通过b1.z访问?
  • @user3735871:这意味着使用b1的代码将只能访问Base定义的东西,即使对象是Derived。这些东西可能是新方法或新领域。就代码使用 b1 而言,b1Base。但是,当使用b1 的代码调用Base 定义但由Derived 实现的对象上的方法时,该方法中的代码可以访问Derived 定义的所有内容。所以是的,b1.z 是不可访问的,但 b1.toString 可以访问 z,因为 b1.toString 是由 Derived 实现的。
  • 谢谢。现在更有意义了!再问一个问题:那么如果Base中没有toString方法,或者Base中没有run()方法,那么Derived类将无法覆盖它来访问z?
  • @user3735871:假设您在Derived 中有一个run 方法,但在Base 中没有。您不能直接从b1 访问run,因为runBase 上不存在,并且您与对象的接口由Base 定义,而不是Derived。现在,如果Base 有一个foo 方法,并且Derived 覆盖了那个foo 方法,那么调用b1.foo 可以调用run,如果这就是Derived 代码为foo 所做的事情(就像你的toString),这就是为什么我说b1 不能直接调用run
  • 谢谢!你解释得很好。
【解决方案2】:

直接来自http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

子类继承其所有公共和受保护成员 parent,无论子类在哪个包中。如果子类是 在与其父级相同的包中,它还继承了 父级的包私有成员。您可以使用继承的 成员按原样替换、隐藏或用新成员补充 成员

在您的代码中,您调用默认构造函数来创建一个新的Derived1 对象:
Base b1 = new Derived();然后这又调用父类的默认构造函数,您恰好在其中设置了x = 10。之后你就到这行int z = x * 2;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-16
    • 1970-01-01
    • 1970-01-01
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多