繁体   English   中英

多态与继承

[英]Polymorphism and inheritance

在这种情况下:

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);

af()调用f()类的B ,然后f() ,分配后,调用s3()函数。 此时, s3()仅在A定义,并且当它向x赋值3时, x是类A拥有的变量的副本。 为什么s3()不使用B声明的x 从理论上讲, B不应该拥有从A继承的s3()函数的副本吗? (因此从B A继承的s3()应该使用B声明的x

您对继承中的操作有误解。 extends是一个明智选择的保留字。 B扩展A的要点是说B是具有附加属性的A的子集。 您不应该在B中重新定义x A应该处理x 通过在子类中重新定义x ,您可以隐藏超类的字段x (即使x引用了不同的变量类型,也是如此)。

A a = new B();
System.out.println(a.x);  //4 makes sense, since we are of class A
B b = (B) a;
System.out.println(b.x);  //5 makes sense, since we are of class B
a.f();
System.out.println(a.x);  //3 makes sense, since a.f() calls s3(), which sets A's x to 3
System.out.println(b.x);  //10 

10之后是打印b的x,通过调用af()将其分配给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 可以。

为什么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();
   }

因此,调用bf()意味着f()等效于:

   public void f(){
      b.x = 10;
      b.s3();
   }

接下来,在A的s3()方法内部会发生什么? s3()看起来像这样:

public void s3(){
      x = 3;
   }

等效于:

public void s3(){
      this.x = 3;
   }

“ this”是调用该方法的对象,在上一个f()示例中,您可以看到它是b。 因此s3()等效于:

public void s3(){
      b.x = 3;
   }

所以bx很快就被3 ...覆盖了!

B的实例也继承了A的x,只是B内的x碰巧B的x 遮蔽了A的x。结果,B中的f()方法将B的x赋给了x。内部s3()但是,从a获得的b的x不再被遮蔽了,就A而言,只有一个x-来自A的x。换句话说,对bx的查找取决于该类是什么而不同语句出现在。

执行s3()之后,最终结果是b具有两个带有两个不同值的x。 在B的方法内部,来自B的x将是可见的,而在A的方法内部,来自A的x将是可见的。 在B的内部方法中,可以使用super从A处获得x。

从理论上讲,B不应该拥有从A继承来的s3()函数的副本吗?

不要以副本来思考。 考虑从类到类的指针,以及从类到查找表的指针。 通常在计算机编程中,每个实例都有其自己的实例变量,但是方法由类中的所有实例共享。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM