Java 多态性与遗传
在这种情况下:Java 多态性与遗传,java,oop,inheritance,polymorphism,Java,Oop,Inheritance,Polymorphism,在这种情况下: class A{ public int x = 4; public void s3(){ x = 3; } public void f(){ x = 8; s3(); } } class B extends A{ public int x = 5; public void f(){ x = 10; s3(); } } A a = new B(); B b = (B) a
class A{
public int x = 4;
public void s3(){
x = 3;
}
public void f(){
x = 8;
s3();
}
}
class B extends A{
public int x = 5;
public void f(){
x = 10;
s3();
}
}
A a = new B();
B b = (B) a;
a.f();
System.out.println(b.x);
System.out.println(a.x);
public void s3(){
x = 3;
}
a.f()
调用类B
的f()
,然后f()
在赋值后调用s3()
函数。此时,s3()
仅在A
中定义,当它将值3赋给x
时,x
是类A
拥有的变量的副本。为什么s3()
不使用B
中声明的x
?理论上,B
不应该有它自己的s3()
函数的副本继承自A
?(因此,从B
中的A
继承的s3()
应该使用B
中声明的x
)您对继承中应该做什么有误解<代码>扩展是一个明智选择的保留字。B扩展A的目的是说B是A的一个子集,具有附加属性。你不应该在B中重新定义x
;A应处理x
。通过在子类中重新定义x
,可以隐藏超类的字段x
(即使x
引用了不同的变量类型,也是如此)
10来自打印b的x,通过调用a.f()
将其分配给10,然后调用s3()
,这就是第三个示例打印3的原因。要了解我的意思,请看以下内容:
public void f()
{
x = 10; //sets B's x to 10
s3(); //calls A's s3(), which sets A's x to 3.
}
你对你在继承中应该做什么有一个误解<代码>扩展是一个明智选择的保留字。B扩展A的目的是说B是A的一个子集,具有附加属性。你不应该在B中重新定义
x
;A应处理x
。通过在子类中重新定义x
,可以隐藏超类的字段x
(即使x
引用了不同的变量类型,也是如此)
10来自打印b的x,通过调用a.f()
将其分配给10,然后调用s3()
,这就是第三个示例打印3的原因。要了解我的意思,请看以下内容:
public void f()
{
x = 10; //sets B's x to 10
s3(); //calls A's s3(), which sets A's x to 3.
}
因为它是一样的。对象没有两个副本(“实例”),只有一个副本 由于您创建的是一个
B
实例(new B()
),它将使用B
中定义的方法。当然,当B
中没有定义方法时,它将使用超类方法实现
因此,您只有一个
x
属性,而s3
强制将其设置为3
。它工作正常。因为它是一样的。对象没有两个副本(“实例”),只有一个副本
由于您创建的是一个B
实例(new B()
),它将使用B
中定义的方法。当然,当B
中没有定义方法时,它将使用超类方法实现
因此,您只有一个x
属性,而s3
强制将其设置为3
。它工作正常
为什么s3()不使用B中声明的x
通常,父类中的方法无法看到子类中的成员变量
我认为这样做:
B b = new B();
b.f();
这足以再现你的一部分困惑。下面是f()在B中的样子:
class B extends A{
public int x = 5;
public void f(){
x = 10;
s3();
}
}
f()相当于:
public void f(){
this.x = 10;
this.s3();
}
public void f(){
b.x = 10;
b.s3();
}
public void s3(){
this.x = 3;
}
public void s3(){
b.x = 3;
}
因此,调用b.f()意味着f()相当于:
public void f(){
this.x = 10;
this.s3();
}
public void f(){
b.x = 10;
b.s3();
}
public void s3(){
this.x = 3;
}
public void s3(){
b.x = 3;
}
接下来,在中的s3()方法内部发生了什么?s3()如下所示:
class A{
public int x = 4;
public void s3(){
x = 3;
}
public void f(){
x = 8;
s3();
}
}
class B extends A{
public int x = 5;
public void f(){
x = 10;
s3();
}
}
A a = new B();
B b = (B) a;
a.f();
System.out.println(b.x);
System.out.println(a.x);
public void s3(){
x = 3;
}
这相当于:
public void f(){
this.x = 10;
this.s3();
}
public void f(){
b.x = 10;
b.s3();
}
public void s3(){
this.x = 3;
}
public void s3(){
b.x = 3;
}
“this”是调用该方法的对象,从f()的最后一个示例中可以看到它是b。因此s3()相当于:
public void f(){
this.x = 10;
this.s3();
}
public void f(){
b.x = 10;
b.s3();
}
public void s3(){
this.x = 3;
}
public void s3(){
b.x = 3;
}
所以b.x被3覆盖了…嗯,不那么快
B的一个实例也从A继承了一个x,只是在B的内部,恰好B的x从A阴影x。因此,B中的f()方法从B赋值给x。在s3()内部,B从A得到的x不再阴影,而就A而言,只有一个x——来自A的x。换句话说,b.x的查找采用不同的路径,具体取决于该语句出现在哪个类中
执行s3()后,最终结果是b有两个x,具有两个不同的值。在B中的方法内部,B中的x将可见,在A中的方法内部,A中的x将可见。在B中的方法中,可以使用super从A获得x
理论上,B不应该有自己的s3()函数的副本继承自A
不要用复制品来思考。考虑从类到类的指针,以及从类到查找表的指针。通常在计算机编程中,每个实例都有自己的实例变量,但方法由类中的所有实例共享
为什么s3()不使用B中声明的x
通常,父类中的方法无法看到子类中的成员变量
我认为这样做:
B b = new B();
b.f();
这足以再现你的一部分困惑。下面是f()在B中的样子:
class B extends A{
public int x = 5;
public void f(){
x = 10;
s3();
}
}
f()相当于:
public void f(){
this.x = 10;
this.s3();
}
public void f(){
b.x = 10;
b.s3();
}
public void s3(){
this.x = 3;
}
public void s3(){
b.x = 3;
}
因此,调用b.f()意味着f()相当于:
public void f(){
this.x = 10;
this.s3();
}
public void f(){
b.x = 10;
b.s3();
}
public void s3(){
this.x = 3;
}
public void s3(){
b.x = 3;
}
接下来,在中的s3()方法内部发生了什么?s3()如下所示:
class A{
public int x = 4;
public void s3(){
x = 3;
}
public void f(){
x = 8;
s3();
}
}
class B extends A{
public int x = 5;
public void f(){
x = 10;
s3();
}
}
A a = new B();
B b = (B) a;
a.f();
System.out.println(b.x);
System.out.println(a.x);
public void s3(){
x = 3;
}
这相当于:
public void f(){
this.x = 10;
this.s3();
}
public void f(){
b.x = 10;
b.s3();
}
public void s3(){
this.x = 3;
}
public void s3(){
b.x = 3;
}
“this”是调用该方法的对象,从f()的最后一个示例中可以看到它是b。因此s3()相当于:
public void f(){
this.x = 10;
this.s3();
}
public void f(){
b.x = 10;
b.s3();
}
public void s3(){
this.x = 3;
}
public void s3(){
b.x = 3;
}
所以b.x被3覆盖了…嗯,不那么快
B的一个实例也从A继承了一个x,只是在B的内部,恰好B的x从A阴影x。因此,B中的f()方法从B赋值给x。在s3()内部,B从A得到的x不再阴影,而就A而言,只有一个x——来自A的x。换句话说,b.x的查找采用不同的路径,具体取决于该语句出现在哪个类中
执行s3()后,最终结果是b有两个x,具有两个不同的值。内部方法一