2011-09-02 72 views
3

我就遇到了這個例子將網上的遺產,我關於它的結果是不容易的。我錯過了一些關鍵的東西。繼承在Java中

public class A { 

int i = 5; 

public A() { 
    foo(); 
} 

private void foo() { 
    System.out.println(i); 

}} 

public class B extends A { 
int i = 6;} 

public class C extends B { 
int i = 7; 

public void foo() { 
    System.out.println("C's foo"); 
    System.out.println(super.i); 
}} 

我試圖弄清是怎麼通過以下命令發生的事情:C c = new C(); System.out.println(C.i);

我知道,當我們創建的C一個新實例我們接近A和B的constructures,所以我們達到A() - (問題1)i(A)正在初始化嗎? 現在我們需要調用foo() - (問題2) - 請問C'S foo()考慮爲A的foo()的重寫?如果B有自己的foo()會怎麼樣?那麼它被認爲是一個覆蓋和C的foo()被操作?

據我所知,沒有覆蓋,當它涉及到局部變量。 System.out.println(c.i)怎麼是7而不是5?難道不應該是最高父親的i

編輯:我的問題是不是該Foo和當我使用C I將被使用,大約是在這兩個特定的命令會發生什麼,造成明顯的使用A的foo和不是C的。

非常感謝。

回答

5

這三個i變量是完全是獨立。哪一個是由任何聲明乃應編譯時確定 - 有沒有多態性參與。因此A.foo()將始終打印出在A中聲明的變量的值。

請注意,這些不是本地變量順便說一句 - 他們是實例變量。

當您打印出使用C中聲明的變量的c.i時,因爲編譯時類型cC。你可以看到這一點,如果你寫:

C c = new C(); 
A a = c; 
B b = c; 
System.out.println(a.i); // 5 - variable declared in A 
System.out.println(b.i); // 6 - variable declared in B 
System.out.println(c.i); // 7 - variable declared in C 

注意,在一個精心編寫的程序,這樣的事情幾乎從來沒有引起一個問題,因爲變量應該是私有的。

+0

Hi jon。通過這兩個命令程序打印:5 7. 爲什麼它首先打印5? – Numerator

+0

@Nir:構造函數調用到'foo()'打印A.i,這是5. –

+0

爲什麼C的foo()沒有被調用?因爲A的foo()是私人的? – Numerator

0

不,你總是使用類成員最接近你實例化的類。所以,C c = new C();將只使用i = 7和C的foo。 B級的我被C級的我覆蓋,就像A的我被B的I覆蓋一樣。 沒有鏈接繼續,只是壓倒一切。

0

A,B,和C各自具有被稱爲 「i」 的一個實例變量。如果你有一個C對象並執行FOO(),您將打印C'S值「I」。

如果你把foo()放在B而不是C中,奇怪的是,如果你有一個C對象,你仍然會得到C的值「i」,因爲將使用「最外層」版本的「i」。

0

關於方法覆蓋和可見性:

A.foo()是私有的。這意味着它的子類是不可見的。如果你想B或C覆蓋A.foo(),A.foo()需要被保護或公開。所以在你的代碼中,Bfoo()不存在,因爲B不知道A.foo()。