简体   繁体   English

多态与继承

[英]Polymorphism and inheritance

In a situation like this: 在这种情况下:

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() calls the f() of the class B , then f() , after an assignment, calls the s3() function. af()调用f()类的B ,然后f() ,分配后,调用s3()函数。 At this point, s3() is only defined in A and when it assigns the value 3 to x , x is the copy of the variable owned by the class A . 此时, s3()仅在A定义,并且当它向x赋值3时, x是类A拥有的变量的副本。 Why s3() doesn't use the x declared in B ? 为什么s3()不使用B声明的x In theory, B shouldn't has its own copy of s3() function inherited from A ? 从理论上讲, B不应该拥有从A继承的s3()函数的副本吗? (so the s3() inherited from A in B should use the x declared in B ) (因此从B A继承的s3()应该使用B声明的x

You have a misunderstanding of what you should be doing in inheritance. 您对继承中的操作有误解。 extends is a reserved word that was wisely chosen. extends是一个明智选择的保留字。 The point of B extending A is to say that B is a subset of A with additional attributes. B扩展A的要点是说B是具有附加属性的A的子集。 You're not supposed to redefine x in B; 您不应该在B中重新定义x A should be handling x . A应该处理x By redefining x in a subclass, you're hiding the superclass' field x (this is true even if x refers to different variable types). 通过在子类中重新定义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 

The 10 follows from printing b's x, which is assigned to 10 with the call of af() , which then calls s3() which is why the 3rd example prints 3. To see what I mean look at this: 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.
   }

Because it is the same. 因为是一样的。 You do not have two copies ("instances") of the object, only one. 您没有该对象的两个副本(“实例”),只有一个。

Since the one you create is a B instance ( new B() ), it will be used the methods as defined in B . 由于您创建的实例是一个B实例( new B() ),因此将使用B定义的方法。 Of course, when no methods are defined in B it will use the superclass methods implementation. 当然,如果在B中未定义任何方法,它将使用超类方法实现。

So, you only have an x attribute and s3 forces it to be 3 . 因此,您只有一个x属性,而s3则将其强制为3 It works ok. 可以。

Why s3() doesn't use the x declared in B? 为什么s3()不使用B中声明的x?

Generally, methods in a parent class cannot see member variables in a child class. 通常,父类中的方法看不到子类中的成员变量。

I think doing just this: 我想这样做:

B b = new B();
b.f();

is enough to reproduce at least part of your confusion. 足以再现您至少部分的困惑。 Here is what f() looks like in B: 这是f()在B中的样子:

class B extends A{
   public int x = 5;
   public void f(){
      x = 10;
      s3();
   }
}

f() is equivalent to: f()等效于:

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

So calling bf() means f() is equivalent to: 因此,调用bf()意味着f()等效于:

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

Next, what happens inside the s3() method in A? 接下来,在A的s3()方法内部会发生什么? s3() looks like this: s3()看起来像这样:

public void s3(){
      x = 3;
   }

and that is equivalent to: 等效于:

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

'this' is the object that called the method, which from the last example of f() you can see is b. “ this”是调用该方法的对象,在上一个f()示例中,您可以看到它是b。 So s3() is equivalent to: 因此s3()等效于:

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

So bx gets overwritten with 3...uhhhhm not so fast! 所以bx很快就被3 ...覆盖了!

An instance of B also inherits an x from A, it's just that inside B it so happens that B's x shadows the x from A. As a result, the f() method in B assigns to the x from B. Inside s3() however, the x that b got from A is not shadowed anymore, and as far as A is concerned there is only one x--the one from A. In other words, the lookup for bx takes a different path depending on what class that statement appears in. B的实例也继承了A的x,只是B内的x碰巧B的x 遮蔽了A的x。结果,B中的f()方法将B的x赋给了x。内部s3()但是,从a获得的b的x不再被遮蔽了,就A而言,只有一个x-来自A的x。换句话说,对bx的查找取决于该类是什么而不同语句出现在。

After s3() executes, the end result is that b has two x's with two different values. 执行s3()之后,最终结果是b具有两个带有两个不同值的x。 Inside methods in B, the x from B will be visible, and inside methods in A, the x from A will be visible. 在B的方法内部,来自B的x将是可见的,而在A的方法内部,来自A的x将是可见的。 Inside methods in B, it is possible to get at the the x from A by using super. 在B的内部方法中,可以使用super从A处获得x。

In theory, B shouldn't has its own copy of s3() function inherited from A? 从理论上讲,B不应该拥有从A继承来的s3()函数的副本吗?

Don't think in terms of copies. 不要以副本来思考。 Think in terms of pointers from class to class, and pointers from classes to lookup tables. 考虑从类到类的指针,以及从类到查找表的指针。 Typically in computer programming, each instance has its own instance variables but methods are shared by all the instances in a class. 通常在计算机编程中,每个实例都有其自己的实例变量,但是方法由类中的所有实例共享。

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

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