2011-06-07 66 views
3

我有價值對象/豆類(只包含成員,無邏輯):Java =什麼是向下轉換的替代品/解決方案?

public class Parent { 
String first; 
String second; 
} 

一些處理邏輯返回「父」。然後我做一些進一步的處理,並要添加furtehr領域:

public class ParentAddedMembers extends Parent { 
String third; 
String fourth; 
} 

的問題是,我不能垂頭喪氣從ParentParentAddedMembers

ParentAddedMembers parentAddedMembers = (ParentAddedMembers) parent; 

這似乎是無效的。 (從我的觀點來看,在這種情況下,當向下轉換未分配的字段時,新的字段只會包含空值,但似乎java不允許這樣做)。

什麼是正確的解決方案,如果我不想手動複製所有字段(我可以寫一個複製方法,將父成員複製到新創建的ParentAddedMembers中,但這不適用於私人字段。如果我在父項中添加/刪除成員,很容易中斷...)

這是什麼對比解決方案?

非常感謝!

馬庫斯

更新: 我想才達到的。我有第三方庫返回一些對象父(來自搜索結果),但我需要添加更多的字段(元數據)。如所描述的向下轉換將很容易地解決問題,但不起作用。我也不能改變父母,因爲它來自第三方庫。

+0

你爲什麼不試圖沮喪工作?你得到的錯誤是什麼?你是怎麼聲明「父母」的?因爲我不明白爲什麼它不應該工作,不管漢堡包和芝士漢堡;-) – 2011-06-07 08:52:08

+3

漢堡包是一個漢堡包嗎? – Kevin 2011-06-07 08:52:12

+1

只要想一想。一切都是對象,但是你不能把蘋果當作汽車,所以你不能把所有東西都貶低爲一切。你試圖建模的真正問題是什麼? – Kaj 2011-06-07 08:52:37

回答

4

(從我在這種情況下來看這將是合法的,向下轉換時未分配,新字段將只需持有空值。但似乎Java不允許這一點)。

時纔有意義直觀,因爲在ParentParentAddedMembers領域對領域相同的名稱。你說你自己有一個複製構造函數由於修改了字段而容易出錯。這種鑄造能力會不會太?(如果將Parent.first更改爲Parent.param1,會發生什麼情況。)

底線是Java不允許這樣做,因爲它在其他情況下沒有意義。你不能投VehicleCar。 (該Vehicle對象可以是Bike。)

什麼是這個corret溶液?

  • 一種選擇是簡單地做

    public class Parent { 
        String first; 
        String second; 
    
        boolean extended; 
        String third; 
        String fourth; 
    } 
    
  • ,或者去你解釋的路線,做一個拷貝構造函數

  • 你也可以使用反射來解決它。然後,您將能夠遍歷Parent的所有字段,並根據字段名稱分配ParentAddedMembers的字段。 (但使用反射表明一些代碼味道其實。)

+0

非常感謝。你有一些有趣的新想法如何解決它。 – Markus 2011-06-07 19:44:43

3

忘掉它,並嘗試瞭解多態以及它在這方面如何幫助你。

[一downvote後編輯]

誰downvoted我,你可能不喜歡我的措辭。但請嘗試理解我說的話。它可能是模糊的,但這意味着不要這樣做,而是使用多態。有一個getter()setter(),使用多態並避免完全投射。

[問題更新後編輯]

然後,你應該考慮尋找到Adapter Pattern

0

我不是說這是總是如此,但是這可能表明一個設計缺陷,如果你需要訪問的對象作爲子類型爲什麼它被引用爲父類型。

然而,要回答你的問題,敷投在if instanceof

1

使用構造函數。

Parent(Parent p) { 
// initalize it 
} 

ParentAddedMembes(Parent p) { 
    super(p); 
    // By default, fields are null 
} 
+1

正確的解決方案 - 如果您爲示例類添加初始化代碼將會更加清晰 – 2011-06-07 08:55:50

+0

他明確表示他希望避免手動複製。 – aioobe 2011-06-07 08:57:26

1

你可以寫一個ParentAddedMembes構造,這樣的構造將採取父對象作爲參數,並與母公司的數據填充本身。

事情是這樣的:

public ParentAddedMembes(Parent parent) { 
    // populate 
} 

再後來

ParentAddedMembes parentAddedMembes = new ParentAddedMembes(parent); 
0

「問題是,我不能垂頭喪氣從家長到ParentAddedMembers」

的問題是,你想不沮喪。你要上溯造型:)

0

的東西,你可以做,當你想使用擴展的成員,檢查類型,然後投:

if(variable instanceof ParentAddressMembers) { 
    ParentAddressMembers pam = (ParentAddressMembers)variable; 
    // you can access pam.third and pam.forth here. 
} else { 
// you can't acces pam.third and pam.forth so better not to bother them. 
} 

讀你更新後,我補充一點:但是,擴展第三方類並不是一個好主意,因爲基類可能會嚴重干擾您的擴展。 (基礎API更改,反射,動態代理等的使用)最好創建一個包含最初返回的第三方對象AS和您的加號字段的包裝類。

1

奇怪,因爲你的代碼是有效的。我的猜測是Parent類型的變量沒有保存的值是ParentAddedMembes

Parent parent = new ParentAddedMembes(); 
ParentAddedMembes pm = (ParentAddedMembes) parent; 

上述代碼是有效的。但是,您可以使用instanceof關鍵字進行向下轉換。例如

Parent parent = new ParentAddedMembes(); 

if (parent instanceof ParentAddedMembes) 
    ParentAddedMembes pm = (ParentAddedMembes) parent; 

這是檢查父母是否是ParentAddedMembes

+0

每當你看到自己使用'instanceof',考慮多態。這就是我在這裏建議的,http://stackoverflow.com/questions/6262780/java-what-are-alternatives-solutions-to-downcasting/6262808#6262808 – 2011-06-07 09:50:05

+0

「父」是*不是* ParentAddedMembers的一個實例'。這只是一個「家長」。它大概編譯,但在運行時拋出ClassCastException。 – aioobe 2011-06-07 09:58:06

+0

@aioobe,啊......然後,在OP的情況下,這是不可能的,通過鑄造。 – 2011-06-07 10:01:02