在以下代码中,我不明白为什么在调用a1.k()
时,this.x
类C
会返回100而不是1.我的理解是this
是指当前对象,但当前变量a1
的静态类型是A
。那么this.x
不应该返回1,这是A类型的变量吗?
我的意思是a1.x
应该返回1
,对吗?非常感谢!
class A {
public int x = 1;
public String k() { return "A" + this.x; }
}
class B extends A {
public int x = 10;
...
}
class C extends B {
public int x = 100;
public String k() { return "C" + this.x; }
}
class TestABC {
public static void main(String[] args) {
A a1 = new C();
C c1 = new C();
System.out.println(a1.k());
}
}
答案 0 :(得分:1)
此功能称为动态多态。被调用的方法不依赖于其声明的类型,而是依赖于它的类型(定义)。
为此,类必须继承并覆盖父类中的方法。
这里C,B扩展A并覆盖方法k;
如果您尝试调用某些特定于C的方法或变量,则会抛出错误。 (因为A不知道)
A持有对C的引用(指向C)
a1.k实际上是C构造的Object及其新的C()。k(),其中x在C中是100。
class Base{
int x=10;
public int getx(){return x;}
}
class Sub extends Base{
int x=100;
public int getx(){return x;}
}
class Test
{
public static void main (String[] args)
{
Base b = new Base();
Sub s = new Sub();
System.out.println("sub: getx:"+s.getx()+" .x:"+s.x+" Class: "+s.getClass().getName());
System.out.println("base: getx:"+b.getx()+" .x:"+b.x+" Class: "+b.getClass().getName());
Base btoS = new Sub();
System.out.println("btos: getx"+btoS.getx()+" .x:"+btoS.x+" Class: "+btoS.getClass().getName());
}
}
结果
sub: getx:100 .x:100 Class: Sub
base: getx:10 .x:10 Class: Base
btos: getx100 .x:10 Class: Sub
答案 1 :(得分:1)
当您致电a1.k()
时,您会动态调度k
方法,该方法由引用位于a1
的实际对象定义。在这种情况下,它是C
而不是A
或B
,因此k
方法是C
中定义的覆盖。
静态类型(例如a1
)用于静态分辨率;例如解析static
方法,重载签名和字段。但是例如方法调用,要调用的方法的最终选择是动态的。
我知道应该调用C类中的k(),而不是类A中的k()。但为什么this.x返回100?我认为实例变量与静态类型有关。
好吧。但是,x
调用中this.x
k()
使用this
的静态类型是C.k
中{{1}} 的静态类型方法正文!
答案 2 :(得分:0)
由于您将a1
声明为new C()
,a1
将被视为类C
的对象实例,它会覆盖其父类{{1}的字段}和B
。那么为什么你会做像A
这样的事情(或者你可能会看到很多这样的实现),有一个建议说"编程接口而不是实际的实现。",我认为this更好地解释了。