對象多態性

多態性,是面向對象的最後一個特徵,也是最重要的特徵,掌握多態性可以設計更好的程序結構。

 

實際上方法的重載就是一種多態性的體現:
       方法名稱相同,根據傳入參數的類型或個數的不同完成的功能也不同。

 

另外一種多態性就是指的對象的多態性:
       · 子類對象向父類對象轉型(向上轉型)
       · 父類對象向子類對象轉型(向下轉型)
       · 對象間的互相轉型問題

 

強調:

       一個類絕對不能繼承一個已經實現好了的類。此處講解的時候只是爲了闡述概念,才使用了類與類的直接繼承,但是開發中此種類型的代碼肯定不存在。

       觀察以下程序,初步認識對象的轉型:
class A{

         public void fun1(){

                   System.out.println("A --> public void fun1(){}") ;

         }

         public void fun2(){

                   this.fun1() ;

         }

};

class B extends A{

         public void fun1(){

                   System.out.println("B --> public void fun1(){}") ;

         }

         public void fun3(){

                   System.out.println("B --> public void fun3(){}") ;

         }

};

       以上代碼可以發現,子類B,繼承了父類A,同時在子類中覆寫了類A中的fun1方法,也增加了自己新的fun3方法。
class A{

         public void fun1(){

                   System.out.println("A1 --> public void fun1(){}") ;

         }

         public void fun2(){

                   this.fun1() ;

         }

};

class B extends A{

         public void fun1(){

                   System.out.println("B1 --> public void fun1(){}") ;

         }

         public void fun3(){

                   System.out.println("B2 --> public void fun3(){}") ;

         }

};

public class Demo10{

         public static void main(String args[]){

                   A a = new B() ;

                   a.fun1() ;

                   a.fun2() ;

         }

};

       以上代碼,無論是直接使用子類,還是子類向父類轉型,發現最終結果調用的都是被子類覆寫過的方法。
       向上轉型的關係:只要發生了向上轉型,則一切的操作方法以子類爲標準。
       如果向上轉型完成之後,那麼一定可以把父類對象變爲子類對象。但是此時就需要強制了。

 

class A{

         public void fun1(){

                   System.out.println("A1 --> public void fun1(){}") ;

         }

         public void fun2(){

                   this.fun1() ;

         }

};

class B extends A{

         public void fun1(){

                   System.out.println("B1 --> public void fun1(){}") ;

         }

         public void fun3(){

                   System.out.println("B2 --> public void fun3(){}") ;

         }

};

public class Demo10{

         public static void main(String args[]){

                   A a = new B() ;

                   B b = (B)a ;

                   b.fun1() ;

                   b.fun2() ;

         }

};

 

       現在觀察以下代碼:
class A{

         public void fun1(){

                   System.out.println("A1 --> public void fun1(){}") ;

         }

         public void fun2(){

                   this.fun1() ;

         }

};

class B extends A{

         public void fun1(){

                   System.out.println("B1 --> public void fun1(){}") ;

         }

         public void fun3(){

                   System.out.println("B2 --> public void fun3(){}") ;

         }

};

public class Demo11{

         public static void main(String args[]){

                   A a = new A() ;

                   B b = (B)a ;

                   b.fun2() ;

         }

};

 

java.lang.ClassCastException

       爲類型轉換異常。兩個沒有任何關係的對象直接進行轉型了,就出現此錯誤。

 

注意:

       如果要進行向下轉型之前,首先必須建立關係,即:必須先發生向上轉型之後,纔可以進行向下轉型。爲了建立關係。

 

對象多態性所帶來的好處?

       對象多態性在傳遞參數上可以體現出其優點,下面看兩組代碼,第一組是沒有使用對象多態性的時候:
class A{

         public void fun1(){

                   System.out.println("A1 --> public void fun1(){}") ;

         }

         public void fun2(){

                   this.fun1() ;

         }

};

class B extends A{

         public void fun1(){

                   System.out.println("B1 --> public void fun1(){}") ;

         }

         public void fun3(){

                   System.out.println("B2 --> public void fun3(){}") ;

         }

};

class C extends A{

         public void fun1(){

                   System.out.println("C1 --> public void fun1(){}") ;

         }

         public void fun3(){

                   System.out.println("C2 --> public void fun3(){}") ;

         }

};

public class Demo12{

         public static void main(String args[]){

                   fun(new B()) ;

                   fun(new C()) ;

         }

         // 定義一個方法,此方法可以接收A的子類對象

         public static void fun(B b){

                   b.fun2() ;

         }

         public static void fun(C c){

                   c.fun2() ;

         }

};

       如果代碼按以上格式編寫會有那些問題?
       · 每增加一個子類,就要增加一個方法,所以可以發現代碼重複修改。
       如果此時使用了對象多態性的概念,則代碼可以修改爲以下結構(所有的操作方法以被子類覆寫過的方法爲標準操作):
class A{

         public void fun1(){

                   System.out.println("A1 --> public void fun1(){}") ;

         }

         public void fun2(){

                   this.fun1() ;

         }

};

class B extends A{

         public void fun1(){

                   System.out.println("B1 --> public void fun1(){}") ;

         }

         public void fun3(){

                   System.out.println("B2 --> public void fun3(){}") ;

         }

};

class C extends A{

         public void fun1(){

                   System.out.println("C1 --> public void fun1(){}") ;

         }

         public void fun3(){

                   System.out.println("C2 --> public void fun3(){}") ;

         }

};

public class Demo13{

         public static void main(String args[]){

                   fun(new B()) ;

                   fun(new C()) ;

         }

         // 不管有多少個子類,都用父類對象接收,因爲可以自動發生向上轉型關係

         public static void fun(A a){

                   a.fun2() ;

         }

};

 

       感覺到一點:在繼承關係中,父類的設計是最重要的,只要父類把功能定義好了,則所有代碼都好寫。
       新的要求:

              現在希望可以對程序的功能稍微有一些擴充,判斷,如果傳入的是B類對象,則可以調用fun3方法,如果傳入的是C類對象,也可以調用C類的fun3方法。
       要完成此功能,肯定要使用向上轉型。
       要完成此功能,必須對傳入對象的類型進行判斷,判斷此對象到底是屬於那個類的實例。

 

instanceof關鍵字完成:
       · 功能:判斷一個對象是否是某個類的實例,返回boolean
       · 語法:對象 instanceof

 

class A{

         public void fun1(){

                   System.out.println("A1 --> public void fun1(){}") ;

         }

         public void fun2(){

                   this.fun1() ;

         }

};

class B extends A{

         public void fun1(){

                   System.out.println("B1 --> public void fun1(){}") ;

         }

         public void fun3(){

                   System.out.println("B2 --> public void fun3(){}") ;

         }

};

class C extends A{

         public void fun1(){

                   System.out.println("C1 --> public void fun1(){}") ;

         }

         public void fun3(){

                   System.out.println("C2 --> public void fun3(){}") ;

         }

};

public class Demo14{

         public static void main(String args[]){

                   fun(new B()) ;

                   fun(new C()) ;

         }

         // 不管有多少個子類,都用父類對象接收,因爲可以自動發生向上轉型關係

         public static void fun(A a){

                   a.fun2() ;

                   if(a instanceof B){

                            B b = (B)a ;

                            b.fun3() ;

                   }

                   if(a instanceof C){

                            C c = (C)a ;

                            c.fun3() ;

                   }

         }

};

 

轉型原則:

       在轉型之前最好先判斷一下一個對象是否是某個類的實例,判斷通過之後在進行向下轉型操作。

 

轉型概念清楚之後就可以利用此概念完善抽象類與接口。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章