程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Java學習 (十三)、面向對象編程(五)多態--對象上下轉型,動態綁定和靜態綁定,應用,面向對象編程多態

Java學習 (十三)、面向對象編程(五)多態--對象上下轉型,動態綁定和靜態綁定,應用,面向對象編程多態

編輯:JAVA綜合教程

Java學習 (十三)、面向對象編程(五)多態--對象上下轉型,動態綁定和靜態綁定,應用,面向對象編程多態


多態

概念:指同一操作作用於某一類對象,可以有不同的解釋,產生不同的執行結果;

存在的必要條件

①   需要存在繼承和實現關系;

②   同樣的方法調用而執行不同操作,運行不同代碼(重寫操作);

③   在運行時父類或者接口的引用變量可以引用其子類的對象;

作用

①   多態通過分離做什麼和怎麼做,從另一個角度將接口和實現進行分離;

②   “多態”則消除了類型之間耳朵耦合關系;

③   多態的存在提高了程序的擴展和後期的可維護性;

1 public class AnimalDemo{ 2 public static void main(String []args){ 3 //父類的引用變量可以引用其子類對象 4 Animal animal1=new Dog("旺財"); 5 animal1.eat(); 6 7 Animal animal2=new Cat("招財"); 8 animal2.eat(); 9 10 } 11 } 12 13 class Animal{ 14 private String name; 15 public Animal(String name){ 16 this.name=name; 17 } 18 19 //這是一個通用的方法,實現沒有太大的意義 20 //只是告訴其子類去實現它 21 public void eat(){ 22 23 } 24 } 25 26 class Dog extends Animal{ 27 public Dog(String name){ 28 super(name); 29 } 30 31 //對父類的方法進行重寫 32 public void eat(){ 33 System.out.println("啃骨頭"); 34 } 35 } 36 37 class Cat extends Animal{ 38 public Cat(String name){ 39 super(name); 40 } 41 42 //對父類的方法進行重寫 43 public void eat(){ 44 System.out.println("吃魚"); 45 } 46 } View Code

對象上下轉型

①   由子類轉型成父類,在繼承圖上是向上移動的,一般稱為向上轉型;

②   向上轉型是從一個較專用類型像較通用類型轉型,所以總是安全的,也就是說,子類是父類的一個超集;

③   向上轉型過程中,類接口中唯一可能發生的事情就是丟失方法,而不是獲取方法;

④   與之相反的操作是向下轉型,不安全(可能需要instanceof操作符協助);

⑤   LSP(liskov替換原則):子類型必須能夠替換掉它們的基類型;

⑥   安全的上轉和LSP的實施,充分體現繼承的“is-a”關系;

 

上面的demo就是向上轉型

1 public class AnimalDemo{ 2 public static void main(String []args){ 3 //父類的引用變量可以引用其子類對象 4 Animal animal1=new Dog("旺財狗");//向上轉型 5 //向上轉型首先是安全的,但可能會導致子類方法的丟失 6 //父類的引用變量只能調用父類中有的方法,或子類中重寫的方法 7 animal1.eat(); 8 //animal1.sleep();//在dog中的特有方法不能使用 9 10 Animal animal2=new Cat("招財貓"); 11 animal2.eat(); 12 13 14 //向下轉型是不安全的 15 //Cat cat=(Cat)animal1;//轉換異常 16 17 } 18 } 19 20 class Animal{ 21 private String name; 22 public Animal(String name){ 23 this.name=name; 24 } 25 26 //這是一個通用的方法,實現沒有太大的意義 27 //只是告訴其子類去實現它 28 public void eat(){ 29 30 } 31 } 32 33 class Dog extends Animal{ 34 public Dog(String name){ 35 super(name); 36 } 37 38 //對父類的方法進行重寫 39 public void eat(){ 40 System.out.println("啃骨頭"); 41 } 42 43 public void sleep(){ 44 System.out.println("睡覺"); 45 } 46 } 47 48 class Cat extends Animal{ 49 public Cat(String name){ 50 super(name); 51 } 52 53 //對父類的方法進行重寫 54 public void eat(){ 55 System.out.println("吃魚"); 56 } 57 } View Code

instanceof運算符用來在運行時通過返回一個布爾值來指出對象是否是特定類或者是它的子類的一個實例;

用法:

         result=object instanceof calss

         result:布爾類型

         object:必選項,任意對象表達式

         class:必選項,任意已定義的對象類

說明:如果object是class或者其子類的一個實例,則instanceof運算符返回true,如果不是或者object是null,則返回false;

典型使用場合:在對對象做下轉型之前,沒有其它有關對象類型信息時務必使用instanceof來判斷一下,以免拋出ClassCastException異常;

1 public class AnimalDemo{ 2 public static void main(String []args){ 3 //父類的引用變量可以引用其子類對象 4 Animal animal1=new Dog("旺財狗");//向上轉型 5 //向上轉型首先是安全的,但可能會導致子類方法的丟失 6 //父類的引用變量只能調用父類中有的方法,或子類中重寫的方法 7 animal1.eat(); 8 //animal1.sleep();//在dog中的特有方法不能使用 9 10 Animal animal2=new Cat("招財貓"); 11 animal2.eat(); 12 13 14 //向下轉型是不安全的 15 //Cat cat=(Cat)animal1;//轉換異常 16 17 //解決方法 18 if(animal1 instanceof Cat){ 19 //未進入 20 System.out.println("進入執行"); 21 Cat cat=(Cat)animal1; 22 } 23 24 if(animal2 instanceof Cat){ 25 //進入 26 System.out.println("進入執行2"); 27 Cat cat=(Cat)animal2; 28 cat.sleep(); 29 } 30 31 } 32 } 33 34 class Animal{ 35 private String name; 36 public Animal(String name){ 37 this.name=name; 38 } 39 40 //這是一個通用的方法,實現沒有太大的意義 41 //只是告訴其子類去實現它 42 public void eat(){ 43 44 } 45 } 46 47 class Dog extends Animal{ 48 public Dog(String name){ 49 super(name); 50 } 51 52 //對父類的方法進行重寫 53 public void eat(){ 54 System.out.println("啃骨頭"); 55 } 56 57 public void sleep(){ 58 System.out.println("睡覺"); 59 } 60 } 61 62 class Cat extends Animal{ 63 public Cat(String name){ 64 super(name); 65 } 66 67 //對父類的方法進行重寫 68 public void eat(){ 69 System.out.println("吃魚"); 70 } 71 72 public void sleep(){ 73 System.out.println("睡覺"); 74 } 75 } View Code

動態綁定和靜態綁定

概念:

①   在程序執行前方法以及被綁定,針對Java簡單的可以理解為程序編譯期的綁定(靜態綁定)java當中的方法是final,static,private和構造方法都是前期綁定的;

②   運行時,根據變量實際引用的對象類型決定調用哪個方法(動態綁定);

靜態綁定在編譯期進行

         Person.sayHi();

動態綁定在運行期進行

         Person p=new Teacher();

         p.sayHi();

多態的概念基於對象引用的動態綁定特性;

 

多態應用

簡單來說,多態是具有表現多種行為能力的特征;

同一個實現接口,使用不同的實例而執行不同操作;

 

不使用多態:

1 public class PrinterDemo{ 2 public static void main(String []args){ 3 ColorPrinter cp=new ColorPrinter("惠普"); 4 BlackPrinter bp=new BlackPrinter("戴爾"); 5 School school=new School(); 6 //school.setColorPrinter(cp); 7 school.setBlackPrinter(bp);//新建的黑白打印時,要修改學習的打印方法 8 school.print("hello java"); 9 10 /*以上每次調用不同的子類時特別麻煩,會影響到其他類中的代碼修改*/ 11 } 12 } 13 14 class Printer{ 15 private String brand; 16 17 public Printer(String brand){ 18 this.brand=brand; 19 } 20 21 public String getBrand() 22 { 23 return brand; 24 } 25 26 //打印方法應該由其子類來具體的實現 27 public void print(String content){ 28 29 } 30 } 31 32 33 //開原原則:對修改是封閉的,對擴展是開放的 34 //可以使用多態解決這個問題,父類的引用變量可以引用其子類的對象 35 class School{ 36 private ColorPrinter cp=null; 37 private BlackPrinter bp=null; 38 private ZhenPrinter bp=null; 39 40 //安裝彩色打印機 41 public void setColorPrinter(ColorPrinter cp){ 42 this.cp=cp; 43 } 44 45 //安裝黑白打印機 46 public void setBlackPrinter(BlackPrinter bp){ 47 this.bp=bp; 48 } 49 50 //安裝針式打印機 51 public void setZhenPrinter(ZhenPrinter bp){ 52 this.bp=bp; 53 } 54 55 public void print(String content){ 56 //交給中心所安裝的彩色打印機來打印 57 //cp.print(content); 58 //交給中心所安裝的黑白打印機來打印 59 bp.print(content); 60 } 61 62 } 63 64 class ColorPrinter extends Printer{ 65 public ColorPrinter(String brand){ 66 super(brand); 67 } 68 //對父類的方法進行重寫 69 public void print(String content){ 70 System.out.println(getBrand()+"彩色打印:"+content); 71 } 72 } 73 74 class BlackPrinter extends Printer{ 75 public BlackPrinter(String brand){ 76 super(brand); 77 } 78 //對父類的方法進行重寫 79 public void print(String content){ 80 System.out.println(getBrand()+"黑白打印:"+content); 81 } 82 } 83 84 class ZhenPrinter extends Printer{ 85 public ZhenPrinter(String brand){ 86 super(brand); 87 } 88 //對父類的方法進行重寫 89 public void print(String content){ 90 System.out.println(getBrand()+"針式打印:"+content); 91 } 92 } View Code

使用多態:

1 public class PrinterDemo{ 2 public static void main(String []args){ 3 ColorPrinter cp=new ColorPrinter("惠普"); 4 BlackPrinter bp=new BlackPrinter("戴爾"); 5 ZhenPrinter zp=new ZhenPrinter("戴爾"); 6 School school=new School(); 7 8 school.setPrinter(zp);//這裡的參數可以調用較靈活,使用cp,bp,zp都可以,而不用改school類中的方法 9 school.print("hello java"); 10 11 } 12 } 13 14 class Printer{ 15 private String brand; 16 17 public Printer(String brand){ 18 this.brand=brand; 19 } 20 21 public String getBrand() 22 { 23 return brand; 24 } 25 26 //打印方法應該由其子類來具體的實現 27 public void print(String content){ 28 29 } 30 } 31 32 33 //開原原則:對修改是封閉的,對擴展是開放的 34 //可以使用多態解決這個問題,父類的引用變量可以引用其子類的對象 35 class School{ 36 private Printer p=null;//安裝打印機 37 38 //拿父類的引用變量作為參數,好處就是可以接受任何其子類的對象 39 //越是抽象的東西就是越穩定的 40 public void setPrinter(Printer p){ 41 this.p=p; 42 } 43 44 public void print(String content){ 45 //交給中心所安裝的打印機來打印 46 p.print(content); 47 } 48 } 49 50 class ColorPrinter extends Printer{ 51 public ColorPrinter(String brand){ 52 super(brand); 53 } 54 //對父類的方法進行重寫 55 public void print(String content){ 56 System.out.println(getBrand()+"彩色打印:"+content); 57 } 58 } 59 60 class BlackPrinter extends Printer{ 61 public BlackPrinter(String brand){ 62 super(brand); 63 } 64 //對父類的方法進行重寫 65 public void print(String content){ 66 System.out.println(getBrand()+"黑白打印:"+content); 67 } 68 } 69 70 class ZhenPrinter extends Printer{ 71 public ZhenPrinter(String brand){ 72 super(brand); 73 } 74 //對父類的方法進行重寫 75 public void print(String content){ 76 System.out.println(getBrand()+"針式打印:"+content); 77 } 78 } View Code

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved