2013-04-07 77 views
1

這可能是一個奇怪的問題,但我不明白我是如何設法實現這個功能的。我的意圖是從覆蓋該領域的對象訪問超級領域。首先,做什麼工作(1):從子類對象訪問超級字段

class Foo { 
    protected int i = 0; 

} 

public class Bar extends Foo { 
    int i = 1; 
    Foo f() { 
     return this; 
    } 
    public static void main (String[] args) { 
     Bar b = new Bar(); 
     System.out.println(b.i); 
     System.out.println(b.f().i); 
    } 
} 

我第一次嘗試使用類似(2):

System.out.println(b.super.i); 

,沒有工作。然後我試圖使用(3):

Foo f() { 
    return super; 
} 

而且這也沒有工作。

所以,參考以上編號的部分:

  1. 爲什麼return this投地美孚返回b.super對象的引用?
  2. main,我會想到b.super將是對實例化對象「b」的超級引用的引用。有沒有辦法從包含對象訪問對超級對象的引用?可能來自反射,但我不想訪問.class對象(b.getClass().getSuper()),而是包含在b中的實例化的Foo。
  3. 爲什麼return.super不返回對b.super對象的引用?
+1

底線:不給同一個名字在超類和子類字段,你會避免頭痛。 – NPE 2013-04-07 08:07:03

回答

2

我的意圖是從覆蓋該字段的對象訪問super的字段。

你不是「壓倒」這個領域。您正在創建第二個不相關的字段,名稱相同。由此產生的名稱衝突是您遇到困難的直接原因。

如果兩個字段不相關,給它們不同的名稱。

如果,另一方面,你正在努力實現多態行爲,把它們變成方法:

class Foo { 
    protected int get_i() { return 0; } 
} 

public class Bar extends Foo { 
    @Override 
    protected int get_i() { return 1; } 
} 
1

你不需要反射,你需要在你的超類中定義setter和getter方法。

1

由於字段不能被覆蓋,所以當您在子類中使用相同的名稱時,它們仍保持隱藏狀態。這就是爲什麼你不能訪問這些超類字段,如果你已經重新定義了子類中的字段。

如果你想訪問這些,你應該在超類中提供getters/setters

1
  1. 因爲字段不是以多態的,動態的方式訪問的。返回的對象的聲明類型是Foo,因此Foo的字段被訪問。字段不能被覆蓋。在子類中定義i會創建另一個與超類中的名稱相同的字段,從而隱藏它。
  2. 沒有辦法。你應該直接訪問對象的字段。改用方法。
  3. 因爲這是無效的Java代碼。 return super是沒有意義的。 super不是一個不同的對象。 superthis是同一個對象。
+0

謝謝。上面的第一個答案讓我嘗試了其他一些東西:將b賦值給Foo('(Foo)b).i')確實可以直接訪問超字段。我知道這會是一種糟糕的形式,但它可以幫助我理解擴展對象如何相互關聯。我肯定會考慮重構,如果它在野外出現;-) – Terry 2013-04-07 08:52:50

1

您的問題回答說:

  1. 爲什麼return.this轉換爲富返回對b.super對象的引用?

    • 它沒有,確切地說。它返回一個對'this'的引用,這是Bar和Foo的一個實例,因爲Bar擴展了Foo。
  2. 在main中,我會認爲b.super是對實例化對象「b」的超級引用的引用。有沒有辦法從包含對象訪問對超級對象的引用?可能來自反射,但我不想訪問.class對象(b.getClass()。getSuper()),而是包含在b中的實例化的Foo。

    • b和b.super是一個也是一樣的。您可以從條形碼訪問Foo保護字段而不會出現問題
  3. 爲什麼return.super不會返回對b.super對象的引用?

    • 此外,b和b.super是相同的實例。
+0

謝謝你的答案。作爲後續,爲什麼'this'必須從Bar內部轉換爲Bar:'Bar b(){return(Bar)this;}'? – Terry 2013-04-07 08:49:06