面向對象的特徵三:多態性

何為多態性:

對象的多態性:父類的引用指向子類的對象(或子類的對象賦給父類的引用)

Person p = new Man();
Object obj = new Date();
多態性的使用:虛擬方法調用

有了對象的多態性以後,我們在編譯期,只能調用父類中聲明的方法,但運行期,我們實際執行的是子類重寫父類的方法。
總結:編譯看左邊;運行看右邊。

多態性的使用前提:

1)類的繼承關係 2)方法的重寫

public class Test {
    public static void main(String[] args) {
      show(new Cat());  // 以 Cat 对象调用 show 方法
      show(new Dog());  // 以 Dog 对象调用 show 方法
                
      Animal a = new Cat();  // 向上转型  
      a.eat();               // 调用的是 Cat 的 eat
      Cat c = (Cat)a;        // 向下转型  
      c.work();        // 调用的是 Cat 的 work
  }  
            
    public static void show(Animal a)  {
      a.eat();  
        // 类型判断
        if (a instanceof Cat)  {  // 猫做的事情 
            Cat c = (Cat)a;  
            c.work();  
        } else if (a instanceof Dog) { // 狗做的事情 
            Dog c = (Dog)a;  
            c.work();  
        }  
    }  
}
 
abstract class Animal {  
    abstract void eat();  
}  
  
class Cat extends Animal {  
    public void eat() {  
        System.out.println("吃鱼");  
    }  
    public void work() {  
        System.out.println("抓老鼠");  
    }  
}  
  
class Dog extends Animal {  
    public void eat() {  
        System.out.println("吃骨头");  
    }  
    public void work() {  
        System.out.println("看家");  
    }  
}

多態性使用的注意點:
對象的多態性,知識用於方法,不適用於屬性(編譯和運行都看左邊)

關於向上轉型和向下轉型(類比基本數據類型):

向上轉型:多態
向下轉型:為了調用子類特有的屬性和方法

image.png

説明:
由於對象有了多態性以後,內存實際上是加載了子類特有的屬性和方法,但是由於變量聲明為父類類型,導致編譯時,只能調用父類中聲明的屬性和方法。子類特有的屬性和方法不能調用。如何才能調用子類特有的屬性和方法呢?使用向下轉型

如何實現向下轉型?
使用強制類型轉換符:()

使用時候的注意點:
使用強轉時,可能出現ClassCastException的異常。
向下轉型時可以使用instanceof進行判斷,一旦返回true就可以向下轉型了,如果返回false就不可進行向下轉型

package com.gavinjoeng.java;
class Fruit{
    public void Name(){
      System.out.println("我叫水果!");
    }
}

class Apple extends Fruit{
    @Override
    public void Name(){
    System.out.println("我叫蘋果!");
    }

}

public class FruitTest{
    public static void main(String[] args) {
        Fruit apple = new Apple();//向上轉型(多態)
        apple.Name();
        Apple apple1 = (Apple)apple;//向下轉型
        apple1.Name();//向下轉型時調用的時子類的屬性
    }
}

輸出:
        我叫蘋果!
        我叫蘋果!

以上為正確的向下轉型
因為apple指向子類對象,所以子類apple1也可以指向apple,向下轉型後都是指向子類對象,所以調用的都是子類的方法

 Fruit apple = new Apple();//向上轉型(多態)
        apple.Name();
        Apple apple1 = (Apple)apple;//向下轉型
        apple1.Name();//向下轉型時調用的時子類的屬性

以下為不安全的向下轉型

Fruit f = new Fruit();
Apple apple3 = (Apple)f;//編譯通過但運行出錯
apple3.Name();

f是父類對象,子類實例apple3不能指向父類。所以為了安全的類型轉換最好使用if(A instanceof B)判斷一下。

你可能感兴趣的:(java)