在java代碼中,人們慣性的認為一個方法中隻能傳回一種傳回值或者無傳回。部落客在做開發過程中碰到了這樣一種情況,安卓用戶端請求資料,背景可能傳回兩種結果(1)通路令牌失效,無資料傳回。(2)正常擷取資料。
這樣的情況下需要根據通路令牌辨別來判斷是否有資料傳回。當無效時傳回使用者重新登入提示,正常時則傳回資料。顯然,傳回的結果有兩種,那麼一個方法裡面隻能傳回一種類型的禁锢使得開發起來略顯笨拙。 使得開發起來相當難受。
思考良久,又結合C++協變傳回類型的啟發。摘抄原文中的一句話: 在C++中,隻要原來的傳回類型是指向類的指針或引用, 新的傳回類型是指向派生類的指針或引用,覆寫的方法就可以改變傳回類型 。這樣的類型稱為協變傳回類型(Covariant returns type).
因為java裡面有沒有指針,是以無法做到以上的功能。但是派生類是包含父類的共有方法和保護方法的。再根據裡氏代換原則(任何基類可以出現的地方,子類一定可以出現),那麼凡是派生類包含的基類屬性,基類一定包含,這樣的話情況會好很多。 那麼隻要由派生類設定屬性傳回到基類中,基類方法一定能操作這些屬性 。那麼一條完整的可變傳回類型就可以建立起來。下面結合代碼來驗證:
首先先定義兩個實體類,代碼如下,
class Person {
/** 假設每個人都有一個名字 **/
String name;
public String getName() {
return name;
}
publicvoid setName(String name) {
this.name = name;
}
}// person
class SuperMan extends Person {
/** 假設每個超人都有身高 **/
int height;
publicint getHeight() {
return height;
}
publicvoid setHeight(int height) {
this.height = height;
}
}// SuperMan
SuperMan類繼承Person類(部落客當時想不出來什麼好東西了- -!),則SuperMan類包含name和height兩個屬性,基類Person隻包含name屬性。
先說明一下普通的操作方式,以此作為對比。代碼如下:
publicstatic Person getPerson1() {
Person person = new Person();
person.setName("無語");
return person;
}
publicstatic SuperMan getSuperMan1() {
SuperMan man = new SuperMan();
man.setName("不知道");
man.setHeight();
return man;
}
很簡單,傳回值就是預期的傳回類型,但是如果把傳回類型替換一下結果如何。如下所示:
publicstatic SuperMan getSuperMan() {
Person person = new SuperMan();
person.setName("小虎");
return (SuperMan) person;
}
以上隻能得到Superman的name屬性無法得到height屬性,如果在傳回之前強轉以此加上height屬性後傳回即可得到一個完整的SuperMan對象。這裡不再嘗試,讀者自行處理。
publicstatic Person getPerson() {
SuperMan man = new SuperMan();
man.setHeight();
man.setName("大明");
return man;
}
以上代碼就是此文章的核心,也是解決文章開頭問題的核心。怎麼操作呢?
我們寫兩個類,ErroMessage和DataMessage類,其中ErroMessage是基類,DataMessage繼承基類。ErroMessage包含erroMessage屬性類型為private,DataMessage包含data屬性。那麼ErroMessage就隻包含erroMessage屬性,操作時隻會引起erroMessage的變化,而不會引起data的變化。而操作DataMessage類時隻能操作data屬性。而在一個方法中,隻要保持方法類型為ErroMessage,傳回時就可以根據需要來傳回相應的類型。這樣使用方法時, 用派生類得到所有屬性,如果子類屬性為空,那麼基類屬性一定不為空。如果派生類屬性不為空,那麼基類屬性一定為空。 這樣就可以按需取得相應的資料。操作起來相當簡單。代碼操作如下:
printDivider("person");
Person person = getPerson();
System.out.println("person的名字是" + person.getName());
SuperMan superMan = (SuperMan) person;
System.out.println("通過強轉擷取到的超人高度是這樣的" + superMan.getHeight());
以上就是部落客對可變傳回類型的了解。
其中核心思想是這樣的: 派生類可以包含基類的共有屬性,那麼基類一定能從派生類擷取到自身暴露給派生類屬性的值 。這是一種逆向思維方式,可能有悖于傳統代碼編寫方式,但是做軟體就是應該嘗試打破傳統思維,縱使道路崎岖不堪。如果有錯誤的話,還望各位讀者提出指正批評意見,共同成長。
FROM:http://www.tuicool.com/articles/qUJFbi