最近一段時間在寫一個類樹的時候,發現了一些關於繼承的值得思考的問題,於是自己寫了簡單的測試代碼進行分析,經過分析與跟csdn論壇朋友的探討,弄清楚了java的一些繼承的機制,但依然有所迷惑。
測試代碼如下:public abstract class A {
int i=1;
public void printI() {
System.out.println("i="+i);
}
}
public class B {
int i=2;
public static void main(String[] args) {
B b=new B();
b.printI();
}
}
上述代碼,抽象類別A有一個資料成員i,有一個提供了實現細目的方法pringI(),然後實體類B繼承了A,擁有一個資料成員i。我的想法是,B繼承了A,自然繼承了方法pringI(),那麼在調用b.printI()時候,應該列印出B中的資料成員變數i的值,但現實與我的想法不一致,b.printI()列印了A中的i的值,就是1。
一直想不明白,在csdn一個網友的協助下,修改代碼如下:public B extends A {
{
i=2;
}
public static void main(String[] args) {
B b=new B();
b.printI();
}
}
這次,程式如我的意圖執行,列印出B中的資料成員i 。
於是我發現了如下問題,B繼承了A,同時繼承了A的方法printI(),但printI()方法執行的是:列印A的資料成員i,在第一段代碼中,B重新定義了繼承自A的資料成員i,並賦值2,而調用printI(),列印的依然是A中的i 。
第二段代碼中,其實如果把i=2放入到main方法中,作用是一樣的,就是,沒有重新定義資料成員i,而是直接修改繼承自A的資料成員i ,所以這個時候列印的i,能夠變成2。
再次修改程式如下:
public abstract class A {
private i=1;
public void printI() {
System.out.println("i="+i);
}
}
public class B extends A {
public static void main(String[] args) {
B b=new B();
b.printI();
}
}
這次編譯收到錯誤:
C:\classes\a>javac B.java
B.java:3: i has private access in A
i=2;
^
1 error
很明顯,由於A中的資料成員被定義為private,那麼B並不能繼承A的i,於是出現上述錯誤。
但如果去掉i=2; ,程式照常執行,因為B調用了A中的方法printI(),而printI()屬於A,所以能夠調用A中的private資料成員i 。
再次修改程式如下:
public class B extends A {
public void printI() {
System.out.println("i="+i);
}
public static void main(String[] args) {
B b=new B();
b.getI();
}
}
上面程式視圖覆寫A中的方法printI(),結果編譯期收到與前一段程式相同的錯誤資訊。
通過幾次程式測試,已經可以確定,子類繼承了父類的方法,如果沒有覆寫該方法,那麼就相當與直接調用父類的方法。
但有一點依然讓我迷惑,就是,如果在A中定義了 int i=1,同時B中再次定義int i=2,那麼B中的i,應該像{ i=2; }一樣,覆蓋並修改了i ,但為什麼第一段程式,列印出來依然是1呢?
這樣一來,繼承的作用值得我懷疑,如果繼承的方法只能調用父類的資料成員或方法,那麼是否只要繼承的方法需要調用到類資料成員或類成員方法,就需要覆寫該方法呢?這樣,繼承的作用好像被收窄了很多,甚至讓我感到失望。