天天看點

第三次學JAVA再學不好就吃翔(part35)--多态向上轉型和向下轉型

學習筆記,僅供參考

文章目錄

  • ​​面向對象​​
  • ​​多态​​
  • ​​多态向上轉型和向下轉型​​
  • ​​多态的好處和弊端​​

面向對象

多态

多态向上轉型和向下轉型

我們首先通過以下代碼複習一下自動類型提升和強制類型轉換:

class BunnyAnimal0602 {
  public static void main(String[] args) {
    int i = 10;
    byte b = 20;
    i = b;       //自動類型提升
    b = (byte)i; //強制類型轉換
    
  }
}      

由此,我們引出多态中的向上轉型和向下轉型:

class BunnyAnimal0602 {
  public static void main(String[] args) {
    Father f = new Son();
    f.method();
  }
}


class Father {
  int num = 10;

  public void print() {
    System.out.println("Print Father");
  }

}


class Son extends Father {
  int num = 20;

  public void print() {
    System.out.println("Print Son");
  }

  public static void method() {
    System.out.println("Method Son");
  }
}      

報錯資訊:

---------- javac ----------
BunnyAnimal0602.java:4: 錯誤: 找不到符号
    f.method();
     ^
  符号:   方法 method()
  位置: 類型為Father的變量 f
1 個錯誤

Output completed (2 sec consumed) - Normal Termination      

父類引用指向子類對象就是向上轉型。同時,我們看到在上述代碼中,由于父類中沒有method方法,是以編譯時報錯。

下面我們通過向下轉型,去調用子類中的method方法:

class BunnyAnimal0602 {
  public static void main(String[] args) {
    Father f = new Son();
    System.out.println(f.num);
    Son s = (Son)f;
    s.method();
  }
}

class Father {
  int num = 10;

  public void print() {
    System.out.println("Print Father");
  }

}

class Son extends Father {
  int num = 20;

  public void print() {
    System.out.println("Print Son");
  }

  public static void method() {
    System.out.println("Method Son");
  }
}      

輸出:

10
Method Son      

記憶體圖:

第三次學JAVA再學不好就吃翔(part35)--多态向上轉型和向下轉型

多态的好處和弊端

  • 多态的好處
  • 提高代碼的維護性
  • 提高代碼的擴充性
  • 多态的弊端
  • 不能使用子類特有的屬性和行為
  • 舉個例子(多态的好處)
class AnimalBunnyCat {
  public static void main(String[] args) {
    method(new Bunny());
    method(new Cat());
    
  }
  public static void method(Animal a) {
    a.eat();
  }
}

class Animal {
  public void eat() {
    System.out.println("動物吃飯");
  }
}

class Bunny extends Animal {
  public void eat() {
    System.out.println("兔子吃胡蘿蔔");
  }
}

class Cat extends Animal {
  public void eat() {
    System.out.println("貓吃魚");
  }
}      

輸出:

兔子吃胡蘿蔔
貓吃魚      
  • 舉個例子(強轉)

基于上面的代碼,我們給method增加一些功能,如果輸入參數是Cat的對象,則增加Cat特有的功能,如果輸入參數是Bunny的對象,則增加Bunny特有的功能:

class AnimalBunnyCat {
  public static void main(String[] args) {
    method(new Bunny());
    method(new Cat());
    
  }
  public static void method(Animal a) {
    if (a instanceof Bunny) {
      Bunny b = (Bunny)a;
      b.eat();
      b.play();
    } else if (a instanceof Cat) {
      Cat c = (Cat)a;
      c.eat();
      c.sleep();
    } else {
      a.eat();
    }
  }
}

class Animal {
  public void eat() {
    System.out.println("動物吃飯");
  }
}

class Bunny extends Animal {
  public void eat() {
    System.out.println("兔子吃胡蘿蔔");
  }
  public void play() {
    System.out.println("兔子玩耳朵");
  }
}

class Cat extends Animal {
  public void eat() {
    System.out.println("貓吃魚");
  }

  public void sleep() {
    System.out.println("貓睡覺");
  }
}      

輸出:

兔子吃胡蘿蔔
兔子玩耳朵
貓吃魚
貓睡覺      

關鍵字​

​instanceof​

​為判斷前面的引用是否是後面的資料類型。如果沒有經過​

​instanceof​

​​判斷,我們可能會把Cat強制轉換為Bunny這樣就會出現類型轉換異常​

​ClassCastException​