Java 繼承與多態(一)

今天在看java編程思想的時候,遇到了一個問題,沒有想明白,於是放在這裏討論一下,一面自己忘記。
先上代碼吧

package test;

import edu.princeton.cs.algs4.StdOut;

class Cycle{
    public int x = 1;
    static void ride(Cycle c){
        System.out.println("" + c);
        System.out.println("the number is :" + c.wheels());
    }
    public int wheels(){
        return this.x;
    }
}

class Unicycle extends Cycle{
    public int x = 2;
    public void f(){
        StdOut.println(x);
    }
}

class Bicycle extends Cycle{
    public int x = 3;
}

class Tricycle extends Cycle{
    public int x = 4;
}

public class test {
    public static void main(String[] args){
        Unicycle uc = new Unicycle();
        Bicycle bc = new Bicycle();
        Tricycle tc = new Tricycle();
        Cycle.ride(uc);
        Cycle.ride(tc);
        Bicycle.ride(bc);
        uc.f();
    }
}

下面是輸出結果

test.Unicycle@15db9742
the number is :1
test.Tricycle@6d06d69c
the number is :1
test.Bicycle@7852e922
the number is :1
2

問題是這樣的:

三個子類都繼承於Cycle父類,並且覆蓋了父類的成員變量x,但是在通過子類對象來調用父類方法的時候,方法中使用的依然是父類自己的成員變量(如上輸出的number都是父類的1).於是就想是不是因爲成員變量沒有覆蓋父類的成員變量。於是寫了一個子類方法輸出了一下,發現成員變量覆蓋成功。那麼問題是什麼呢?或者說,我要如何才能通過多態來調用子類成員變量,而不用重寫一遍父類方法?(有點繞,看輸出就明白了,我想通過父類的wheels來調用子類的x變量。)

我的理解:

我自己在查了一些別人的問題與解決,發先一些原理。

  • 第一 子類在繼承父類的過程中,會把父類的所有方法與成員變量都Copy一邊,放在自己的super域(可以通過super關鍵字主動訪問,private不能訪問),在子類調用一個方法的時候,會先在自己的this域內搜索是否含有該方法,沒有發現,就會向上轉型,到super域進行訪問,找到該方法後便開始執行,在執行的過程中因爲就近原則(看網友這麼說的,不知道這個就近原則準不準確),方法中調用的成員變量會是父類的成員變量,於是纔會有我現在的結果。

  • 第二 也是別人總結的一個規律“成員變量的調用與調用的引用類型嚴格一致”即這個成員變量的調用與調用時所用的引用類型一致,下面有一個例子,大家一看一看就明白

class Base2 {
  int i = 1;
  String s = "Base";
}

class Child2 extends Base2 {
  int i = 9;
  String s = "Child";
  public static void main(String[] args) {
    Child2 c1 = new Child2();
    Base2 c2 = new Child2();
    System.out.println(c1.i);
    System.out.println(c1.s);
    System.out.println(c2.i);
    System.out.println(c2.s);
  }
}

以下是輸出結果:

9
Child
1
Base

也許在後面學習了其他機制以後就知道怎麼做了吧,我隱約記得有個Class類型,支持向下轉型。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章