簡體   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