iT邦幫忙

2023 iThome 鐵人賽

DAY 20
0

又稱為多態性或同名異式

Java 參照變數有兩個類型:一個是編譯時的類型,一個試運行時的類型。

編譯時類型由宣告該變數時的類型決定,運行時類型由實際賦給該變數的物件決定,如果編譯時類型和運行時類型不一致,就會出現所謂的多型。

只要具備繼承關係,不管是資源的繼承 (extends) 或抽象的繼承(implements),都適用多型規則

多型的目的:

  1. 使用同一個父類類型,但執行不同的子類物件實例。
  2. 會依其操作的子類物件實例來切換方法(method) 。

複習之前所提到的:

我們要產生單一類型物件:

父類別名稱 變數 = new 父類別名稱();  
子類別名稱 變數 = new 子類別名稱();

如果要使用多型的方式產生物件會有以下限制:

 父類別名稱 變數 = new 子類別名稱();
  1. 只能放入與左邊類型有關的物件
  2. 左邊:類型,有限制意思, 只能使用該類型定義的屬性(值)與方法名
    右邊:物件,代表方法執行"子類新"的內容

以下用舉例來說明:

class Card{
	String name = "信用卡";
	float bonus = 1.0f;
	int park = 3;
	@Override
	public String toString() {
		return "Card [name=" + name + ", bonus=" + bonus + ", park=" + park + "]";
	}	
	void showName() {
		System.out.println(name);
	}
}
//------------------------
class OilCard extends Card{
	String name = "加油卡";
	float bonus = 1.5f;
	boolean gift = true;
	//int park = 3;
	@Override
	public String toString() {
		return "OilCard [name=" + name + ", bonus=" + bonus + ", gift=" + gift + ", park=" + park + "]";
	}
	void showName() {
		System.out.println(name);
	}
}
//------------------------
class ShoppingCard extends Card{
	String name = "購物卡";
	float bonus = 2.0f;
	int park = 10;
	boolean birth = true;
	@Override
	public String toString() {
		return "ShoppingCard [name=" + name + ", bonus=" + bonus + ", park=" + park + ", birth=" + birth + "]";
	}	
	void showName() {
		System.out.println(name);
	}
}
public class Ploy01 {
	public static void main(String[] args) {
		//單一類型物件
		Card c1 = new Card();
		System.out.println(c1);
		
		OilCard c2 = new OilCard();
		System.out.println(c2);
		
		ShoppingCard c3 = new ShoppingCard();
		System.out.println(c3);
		
		//-----------------------------
		//父 = 子
		Card[] cs = {c1, c2, c3};
		
		//以下只會印出信用卡,因為屬性只會用左邊類別定義的
		System.out.println(cs[0].name);
		System.out.println(cs[1].name);
		System.out.println(cs[2].name);
		//以下會印出個別定義的名稱,因為方法執行內容會採取右邊的方法內,會先搜尋該類別有沒有定義同名變數
		cs[0].showName();
		cs[1].showName();
		cs[2].showName();
	}
}

那我們在定義一個方法get()來說明

public static void get(Card c){
	System.out.println(c.name);
	c.showName();
}

public static void main(String[] args) {
	get(new Card());//意思是:Card c = new Card();
	get(new OilCard());//意思是:Card c = new OilCard();
	get(new ShoppingCard());//意思是:Card c = new ShoppingCard();
}

/*
信用卡
信用卡
信用卡
加油卡
信用卡
購物卡
*/

如果使用多型時,若子類別有父類別未定義的方法是否可以使用呢?

答案是NO!

因為左邊是編譯時的類型,所以編譯時無法呼叫到父類別未定義的方法

Instanceof 運算子

用於判斷前面的類別是不是後面的類別、其子類別、實作類別的實例

如果是返回true ,否返回false

參照變數強制類型轉換

語法:

(型態) 變數;
  1. 向上轉型(子轉父): 物件向上轉換成基礎(父)類別的型別

  2. 基本類型轉型

    只能在數值類型之間進行,包括整數、浮點數、字元,數值和布林值類型不能轉換

  3. **向下轉型:**將父類別轉換成子類別

語法:

子類別類別名稱 子類別參考變數名稱 = (子類別類別名稱) 父類別參考變數名稱;

向下轉型的安全性

向下轉型是一個較不安全的操作,。因為它可能導致執行時期的異常(ClassCastException)。

常常發生『編譯會過,執行會錯』,因為母類別不一定擁有子類別的欄位,所以不能這樣轉換。為了確保轉換的安全性,您應該使用 instanceof 運算子來檢查父類別參考變數是否實際上指向子類別的對象。這樣可以避免不必要的異常。

今天就到這裡,明天繼續!!!


上一篇
Day 19 封裝(Encapsulation)IV
下一篇
Day 21 其他類 I
系列文
玩轉Java:從基礎打造你的程式超能力30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言