Java物件導向四大特性_多型 ——戀天小結

2020-08-09 10:27:04

多型

軟體設計六大原則

		1 單一職責原則 : 功能職責單一,只擁抱一種變化
		2 裡氏替換原則 : 所有在使用父類別的情況下,都可以使用子類替換
		3 依賴倒置 : 通過高層的抽象依賴底層,細節依賴抽象
		4 介面隔離原則
		5 迪米特原則
		6 開閉原則 : 對擴充套件開放,對修改關閉

多型前提條件

	有繼承關係

多型的幾種形式

	1 區域性變數/成員變數 : 宣告的時候 使用父類別宣告,賦值的時候,使用子類物件
	
	2 實參/形參 : 參數列表使用父類別宣告變數,方法呼叫時傳入子類物件
	   			
	3 返回值 : 返回值型別使用父類別宣告,return的時候 返回子類物件
	
	**多型發生在賦值的時候**
		Animal a ; // 宣告一個變數,不是多型
		   		a = new Animal();  父類別參照指向父類別物件,不是多型
		   		a= new Cat(); : 父類別參照指向子類物件,多型

多型缺點

	丟失子類特有的屬性

父類別參照指向子類物件

	參照 : 參照型別變數
	
	指向 : 就是通過這個參照型別的變數儲存的記憶體地址,可以找到誰
	
	子類物件 : 就是使用子類建立的物件 
	
	使用父類別型別宣告一個變數,這個變數儲存子類物件的記憶體地址,
	
	哪裏 有變數,哪裏就能發生多型

語法

	 父類別 變數名 = new 子類()
		1 如果父類別沒有,不管子類有沒有,不管什麼屬性,都存取不了,報錯
		2 如果父類別有的成員方法,子類也有的成員方法,執行子類,因爲覆寫
		3 如果父類別有的成員方法,子類沒有,執行父類別
		 4 如果父類別有的非成員方法,不管子類有沒有,都執行父類別
public class Poly_01 {
           public static void main(String[] args) {
        	   Sup sup = null;
        	   sup.m1();
        	   System.out.println(sup.i);
      //  	   System.out.println(sup.a);
        	   
           }
}
class Sup{
	int i = 10;
	public void m1() {
		System.out.println("父類別成員方法");
	}
}
class Sub extends Sup{
	int i = 20;
	int a = 1;
	public void m1() {
		System.out.println("子類成員方法");
	}
}

多型的好處

	  參數使用父類別宣告,可以接收所有子類物件
	   後續想要進行功能擴充套件的時候,不需要改動原始碼
public class Poly_02 {

	public static void main(String[] args) {
		 Cat c = new Cat();
		 Dog d = new Dog();
		 eat(c);
		 eat(d);
		 Animal a = new Cat();

	}
	public static void eat(Animal animal) {
		//判斷animal是否由cat範例化而來
		if(animal instanceof Cat) {
			//向下轉型
			Cat c1 = (Cat) animal;
			//TODO 可以存取特有屬性了
		}else if(animal instanceof Dog){
			Dog d1 = (Dog)animal;
		}
		animal.eat();
	}

}
class Animal{
	public void eat() {
		System.out.println("動物吃東西");
	}
}
class Cat extends Animal{
	public static final int age = 1;
	

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

	public static final int age = 1;

	public void eat() {
		System.out.println("狗吃肉");
	}
}

多型又叫向上轉型

	自動型別轉換:
					1 基本型別 : 低精度到高精度
		   			2 參照型別 : 子類到父類別	

	 instanceof 運算子 : 判斷某個物件是否由某個類範例化而來,可以避免強制型別轉換異常
public class Poly_03 {

	public static void main(String[] args) {
				Animal animal = new Cat();
				//多型丟失子類特有屬性
				//System.out.println(animal.age);
				
				//需要先向下轉型
				Cat c = (Cat) animal;
				System.out.println(c.age);
				
				//如果把Cat轉換爲Dog型別 會報錯
				Dog d = (Dog)animal;
				
				//判斷之後名可以避免型別轉換異常
				if (animal instanceof Cat) {
					Cat c1 = (Cat) animal;
					System.out.println(c1.age);
				}else if ( animal instanceof Dog) {
					Dog d1 = (Dog) animal;
					System.out.println(d1.age);
				}
	}

}

隱祕的一個多型

通過子類,呼叫父類別的方法的時候,父類別的這個方法中的上下文環境 就會發生多型(屬於父類別空間,子類物件)

public class Poly_04 {

	public static void main(String[] args) {
		SubClass sub = new SubClass();
		System.out.println(sub);
	//	System.out.println(sub.i);
		sub.m1();
	}

}
class SupClass{
	int i = 10;
	int asdasdacxz12 = 2;
	public void m1() {
		/**
		 * this:儲存當前類物件的記憶體地址,並且是一個成員物件,那麼this的數據型別是什麼?
		 * 
		 * 當前類:this在那個類體中,那個就是就是當前類
		 * 
		 * 當this的數據型別是什麼的時候,可以儲存當前類物件的記憶體地址?
		 * 1 當前類型別
		 * 2 父類別型別
		 * 
		 * 如果是父類別型別,會發生多型,丟失子類特有的屬性,經過測試,可以使用this呼叫當前類中
		 * 特有的屬性,所以this的型別一定是當前類型別
		 * 
		 * SupClss this;
		 * 
		 * 誰呼叫的這個方法,this就指向誰
		 * 
		 * 這個m1方法是誰呼叫的?
		 *            如果是當前類物件呼叫的,this就指向當前類物件
		 *            但是如果是子類物件呼叫,this就指向子類物件
		 * 結合起來  就成了
		 *                SupClass this = new SubClass(); 發生多型
		 *                
		 */
		// System.out.println(this.asdjhaskhdask123123bdkas);
				System.out.println(this);
				System.out.println(this.i);
				
				//呼叫不了
				// System.out.println(this.b);
				m2();
	}
	public void m2() {
		System.out.println("父類別m2執行");
	}
}
class SubClass extends SupClass{
	int i = 33;
	int b = 2;
	 
	public void m2() {}
}