關於java可變(協變)返回類型的解說之一------------基類與派生類


  在java代碼中,人們慣性的認為一個方法中只能返回一種返回值或者無返回。博主在做開發過程中碰到了這樣一種情況,安卓客戶端請求數據,后台可能返回兩種結果(1)訪問令牌失效,無數據返回。(2)正常獲取數據。

  這樣的情況下需要根據訪問令牌標識來判斷是否有數據返回。當無效時返回用戶重新登錄提示,正常時則返回數據。顯然,返回的結果有兩種,那么一個方法里面只能返回一種類型的禁錮使得開發起來略顯笨拙。使得開發起來相當難受。

  思考良久,又結合C++協變返回類型的啟發。摘抄原文中的一句話:在C++中,只要原來的返回類型是指向類的指針或引用,新的返回類型是指向派生類的指針或引用,覆蓋的方法就可以改變返回類型。這樣的類型稱為協變返回類型(Covariant returns type).

  因為java里面有沒有指針,所以無法做到以上的功能。但是派生類是包含父類的共有方法和保護方法的。再根據里氏代換原則(任何基類可以出現的地方,子類一定可以出現),那么凡是派生類包含的基類屬性,基類一定包含,這樣的話情況會好很多。那么只要由派生類設置屬性返回到基類中,基類方法一定能操作這些屬性。那么一條完整的可變返回類型就可以建立起來。下面結合代碼來驗證:

  首先先定義兩個實體類,代碼如下,

  

 1 class Person {
 2     /** 假設每個人都有一個名字 **/
 3     String name;
 4 
 5     public String getName() {
 6         return name;
 7     }
 8 
 9     public void setName(String name) {
10         this.name = name;
11     }
12 
13 }// person
14 
15 class SuperMan extends Person {
16     /** 假設每個超人都有身高 **/
17     int height;
18 
19     public int getHeight() {
20         return height;
21     }
22 
23     public void setHeight(int height) {
24         this.height = height;
25     }
26 }// SuperMan

  SuperMan類繼承Person類(博主當時想不出來什么好東西了- -!),則SuperMan類包含name和height兩個屬性,基類Person只包含name屬性。

  先說明一下普通的操作方式,以此作為對比。代碼如下:

  

1 public static Person getPerson1() {
2         Person person = new Person();
3         person.setName("無語");
4         return person;
5     }

 

1 public static SuperMan getSuperMan1() {
2         SuperMan man = new SuperMan();
3         man.setName("不知道");
4         man.setHeight(120);
5         return man;
6     }

  很簡單,返回值就是預期的返回類型,但是如果把返回類型替換一下結果如何。如下所示:

  

1 public static SuperMan getSuperMan() {
2         Person person = new SuperMan();
3         person.setName("小虎");
4         return (SuperMan) person;
5     }

  以上只能得到Superman的name屬性無法得到height屬性,如果在返回之前強轉以此加上height屬性后返回即可得到一個完整的SuperMan對象。這里不再嘗試,讀者自行處理。

  

1 public static Person getPerson() {
2         SuperMan man = new SuperMan();
3         man.setHeight(100);
4         man.setName("大明");
5         return man;
6     }

  以上代碼就是此文章的核心,也是解決文章開頭問題的核心。怎么操作呢?

  我們寫兩個類,ErroMessage和DataMessage類,其中ErroMessage是基類,DataMessage繼承基類。ErroMessage包含erroMessage屬性類型為private,DataMessage包含data屬性。那么ErroMessage就只包含erroMessage屬性,操作時只會引起erroMessage的變化,而不會引起data的變化。而操作DataMessage類時只能操作data屬性。而在一個方法中,只要保持方法類型為ErroMessage,返回時就可以根據需要來返回相應的類型。這樣使用方法時,用派生類得到所有屬性,如果子類屬性為空,那么基類屬性一定不為空。如果派生類屬性不為空,那么基類屬性一定為空。這樣就可以按需取得相應的數據。操作起來相當簡單。代碼操作如下:

  

1 printDivider("person");
2         Person person = getPerson();
3         System.out.println("person的名字是" + person.getName());
4         SuperMan superMan = (SuperMan) person;
5         System.out.println("通過強轉獲取到的超人高度是這樣的" + superMan.getHeight());

  以上就是博主對可變返回類型的理解。

  其中核心思想是這樣的:派生類可以包含基類的共有屬性,那么基類一定能從派生類獲取到自身暴露給派生類屬性的值。這是一種逆向思維方式,可能有悖於傳統代碼編寫方式,但是做軟件就是應該嘗試打破傳統思維,縱使道路崎嶇不堪。如果有錯誤的話,還望各位讀者提出指正批評意見,共同成長。

  最后博主寫了一個小demo,下載地址是:http://download.csdn.net/detail/tianqianya/8321397

  下一次則將說明接口的可變返回類型。敬請期待~  ^_^

  QQ群號433409373 ->老夫在此等候小伙伴一起學習探討交流~~~共建學習平台                                                                 

 

 

 

 

 

 

 

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM