Java更宽的对象分配转换
在下面的例子中,我不明白为什么Base b1 = new Derived(); System.out.println(b1);
打印出x=10, z=20
。我的理解是,因为b1
有一个静态类型的基地,它不能访问Derived
中的字段,所以z
不应该打印出来。有人可以帮忙解释吗?非常感谢!Java更宽的对象分配转换
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;
}
}
的对象是Derived
,而不是一个Base
。您的接口到b1
的对象是Base
。 Base
有toString
,所以你可以访问toString
。您访问的实现是对象所具有的实现,它由Derived
提供,它使用z
。 Derived#toString
的实现可以访问z
,因为其对对象的引用是通过Derived
引用(this
)引用的,而不是Base
引用。
正如Oli在评论中指出的那样,这对多态性具有根本性 —使对象的行为取决于对象而不是对象的接口。
如果对象的内部是由我们所需的接口决定的,那么尝试执行interface
s就会遇到一些麻烦! :-)
谢谢!我仍然有点困惑,因为我记得老师说过这样的话:“这个更广泛的任务是可以的,但是b1不能访问Derived中的字段。”那么这是指什么?这是否意味着它可以通过方法访问z,就像你说的,但它不能通过b1.z访问? – user3735871 2014-09-13 09:33:51
@ user3735871:这意味着使用'b1'的代码只能访问'Base'定义的东西,即使对象是一个Derived。这些可能是新方法或新领域。就代码*使用*'b1'而言,'b1'是一个'Base'。但是,当使用'b1'的代码调用由'Base'定义但由Derived实现的对象的方法时,该方法中的代码可以访问Derived定义的所有内容。所以是的,'b1.z'不可访问,但'b1.toString'可以访问'z',因为'b1.toString'由'Derived'实现。 – 2014-09-13 09:38:31
谢谢。现在它变得更有意义!还有一个问题:如果Base中没有toString方法,或者Base中没有toString方法,那么Derived类将无法覆盖它来访问z? – user3735871 2014-09-13 09:50:04
直接从http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
子类继承其所有 母公司的公共和保护的成员,无论子类是在什么包,如果子类在同一个包 它的父项,它也继承父项的包私有成员 。您可以使用继承 成员是,取代他们,隐藏起来,或者用新 成员
在你的代码调用默认的构造函数来创建一个新的Derived1
对象加以补充:Base b1 = new Derived();
,这反过来又调用父类的默认构造函数,在那里你碰巧设置了x = 10
。之后,你去这条线int z = x * 2;
这是多态性的全部目的。 – 2014-09-13 09:20:08
https://en.wikipedia.org/wiki/Method_overriding – khelwood 2014-09-13 09:34:27