多態

多態的引出

【多態的體現】                                                                                                                                                                                       父類的引用或者接口的引用指向自己的子類對象。

Dog d=new Dog();
Animal a=new Dog();

【多態的好處】                                                                                                                                                                                      提高了程序的擴展性

【多態的弊端】                                                                                                                                                                                        通過父類引用操作子類對象時,只能使用父類中已有的方法不能操作子類持有的方法

【多態的前提】                                                                                                                                                                                       1. 必須有關係:繼承或實現。

 2. 通常都有重寫操作。

 

【在多態的情況下調用子類的特有方法】

Animal a=new Dog();

Animal 是父類型,new Dog()是子類型。但是父類型引用指向子類對象時,這就是讓子類對象進行類型的提升(向上轉型)。

向上轉型的的好處:提高了擴展性,隱藏了子類型;弊端:不能使用子類型的特有方法。

如果要想使用子類的特有方法,可以向下轉型(強制轉換):

Animal a=new Dog();
a.eat()//這是Animal的方法,可以直接這樣用
Dog d=(Dog)a;//將a轉型爲Dog類型,向下轉型
d.lookHome();

當需要使用子類型的特有內容時使用向下轉型。

注意:無論向上還是向下轉型,最終都是子類對象做着類型的轉換。

【向下轉型的注意實項】

Animal a=new Dog();

Cat c=(Cat)a;

像上面這個錯誤的例子說明向下轉型不明確具體子類對象類型,所以容易引發ClassCastException異常。所以爲了避免這個問題,需要在向下轉型前判斷類型

判斷類型的關鍵字爲:instanceof

abstract public class Animal {
  abstract void eat();
}


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


public class Dog extends Animal {
	public void eat()
	{
		System.out.println("骨頭");
	}
	
	public void speak()
	{
		System.out.println("wangwang");
	}
}


public class Test {

	public static void main(String[] args) {
		Animal a1=new Dog();
		method(a1);
		
		Animal a2=new Cat();
		method(a2);
	}
	
	public static void method(Animal A)
	{
		if(A instanceof Cat)
		{
			Cat c=(Cat)A;
			c.eat();
		}
		
		else if(A instanceof Dog)
		{
			Dog d=(Dog)A;
			d.eat();
		}
	}
}


結果:骨頭
      魚

【轉型的總結】

1.問題:什麼時候向上轉型?

  答案:不關係子類型。不需要子類的特有方法

2. 問題:什麼時候向下轉型?

   答案:需要使用子類型的特有方法時,但是一定要使用instanceof進行類型的判斷,避免ClassCastException。

 

【練習】(見https://blog.csdn.net/weixin_43677405/article/details/104098204) 

【多態的成員調用的特點】

1. 成員變量

當子父類中出現同名的成員變量時,多態調用該變量時,

編譯時期,參考的是引用型變量所屬的類中是否有被調用的成員變量。如果沒有該變量就編譯失敗

運算時期,也是調用引用型變量所屬的類中的成員變量。

簡單記:編譯和運都參考等號的左邊。

就比如下面這個例子:

public class Fu {
int num=3;
}


public class zi extends Fu{
	int num=9;
}


public class DuoTaiDemo {
	public static void main(String[] args) {
		Fu f=new zi();
		zi z=new zi();
		System.out.println(f.num);
		System.out.println(z.num);
	}
}

結果:3
      9

 

 2. 成員函數(對於成員函數是動態綁定到對象上

編譯:參考左邊,如果沒有,編譯失敗。

運行:參考等號右邊的類。

簡單記:編譯看左,運行看右。

public class Fu {
    void show()
    {
	    System.out.println("Fu show");
    }
}


public class zi extends Fu{
	void show()
	{
		System.out.println("zi show");
	}
}


public class DuoTaiDemo {
	public static void main(String[] args) {
		Fu f=new zi();
		zi z=new zi();
		f.show();
		z.show();
	}
}

3. 靜態函數(靜態函數是靜態綁定到類上

編譯和運行看左邊。

(真正的開發時靜態方法是不會被多態調用的,因爲靜態方法不屬於對象,而是所屬於類的。)

public class Fu {
   static void show()
   {
	   System.out.println("Fu static show");
   }
}


public class zi extends Fu{
static void show()
	{
		System.out.println("zi static show");
	}
}


public class DuoTaiDemo {
	public static void main(String[] args) {
		Fu f=new zi();
		zi z=new zi();
		f.show();
		z.show();
	}
}


結果:Fu static show
     zi static show

【結論】

對於成員變量和靜態函數,編譯和運行都看左邊。

對於成員函數,編譯看左邊,運行看右邊。

 

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