2013-04-04 62 views
10
public class Base { 
    //long list of attributes 
    // no Constructor using fields 
    // no init methode 
    // i cannot change this class 
} 

現在初始化子類我擴展基類,如:java中,從超類

public class subClass extends Base{ 
    private boolean selected; 

    ... 
    getter und setter 
    ... 
} 

我成爲基本對象的列表List<Base>

但我需要相同的列表而是作爲List<SubClass> 是有一種方法可以從基類中初始化子類?

例如:

for(Base b: list){ 
    SubClass sub = (SubClass)b; // Thats wrong i know 
    if(...){ 
     sub.setSelected(true); 
    } 
    newList.add(sub); 
} 

我儘量避免基Class的每個屬性的手動初始化子類

更新我的問題是在意見中的要求: 上面的設計僅僅是一個例子。我QUESTIN完全是:

爲什麼將BaseClass轉換爲子類(sence Subclass extends BaseClass)是不可能的?爲什麼Java的不到風度讓我做到以下幾點:

例如:

Class Base{ 
    private String name; 
..... 
} 
Class SubClass extends Base{ 
    private String title; 
} 

然後

Base b = DBController.getById(...); 
SubClass sub = (SubClass)b; 

的對象sub應具備的屬性名稱從對象b 和後title屬性爲null

爲什麼在java中不是這種情況?

對不起我的英文不好, 感謝

+2

從超類初始化子類 - 爲什麼?這聽起來有些不妥,最壞的情況是危險的。 – 2013-04-04 04:03:27

+0

「列表」字段在哪裏定義?在'Base'類中呢?你是否能夠控制其聲明的位置以及初始化位置? – Perception 2013-04-04 04:05:04

+1

我強烈建議你看看「寧願組成比繼承」 - 谷歌它。你會發現一些有趣的討論。我只是這樣說,因爲它看起來像你試圖拼命濫用特權。 – 2013-04-04 04:10:34

回答

7

如果你有一個List<Base>,則無法將其轉換爲List<SubClass>。這主要是因爲該列表可能不包含​​的實例。你能做的最好的是:

List<SubClass> newList = new List<SubClass>(); 
for(Base b: list){ 
    if (b instanceof SubClass) { 
     SubClass sub = (SubClass)b; 
     . . . 
     newList.add(sub); 
    } 
} 

但是一般來說,當你發現自己在做這樣的事情,有什麼不對您的設計。您可能想要避免繼承Base並使用composition instead

編輯根據您的意見,這聽起來像你想用Base實例作爲開始的列表來構建​​實例的列表。一種方法是爲​​定義一個構造函數,將Base作爲參數。

public class SubClass extends Base{ 
    private boolean selected; 

    public SubClass() { 
     // default constructor 
    } 

    public SubClass(Base original) { 
     // copy constructor -- initialize some fields from 
     // values in original, others with default values 
    } 
    ... 
    getter und setter 
    ... 
} 

然後你就可以用你的建設新的列表:

List<SubClass> newList = new List<SubClass>(); 
for(Base b: list){ 
    SubClass sub = new SubClass(b); 
    . . . 
    newList.add(sub); 
} 
+0

感謝您的答案。 List只有Object的基類型,所以它們不是列表中Subclass的實例。但爲什麼施放類是錯誤的? SubClass中的屬性在投射後可以爲null,我可以像上面的示例中那樣將其設置爲manualy。你對此有何感想? – 2013-04-04 04:27:44

+0

我的意思是,鑄造後SubClass應具有基類的所有屬性,其餘屬性在SubClass中將爲null – 2013-04-04 04:34:07

+0

@ Rami.Q - 好的,您的意見向我澄清了一些關於您想要的東西。我修改了我的答案來解決這個問題。 – 2013-04-04 06:20:42

2

你似乎有很多的屬性和設置他們都沒有簡單的方法的類。你現在遇到了一個問題,你需要一個具有附加屬性的類,但你必須處理基類的混亂。

我建議,而不是創建一個子類,鑄造,創建醜圍繞着一個包裝類:

public class BigDumbClass { 
    // A lot of attributes 
    // No Constructor 
    // No init method 
} 

public class Wrapper { 
    private BigDumbClass base; 
    private boolean selected; 

    public Wrapper(BigDumbClass base) { 
     this.base = base; 
     this.selected = false; 
    } 

    //getters and setters 
} 

現在,當你要創建一個新的列表中,您可以在舊列表包裹一切

List<BigDumbClass> oldList = someData(); 
List<Wrapper> wraps = aNewList(); 
for (BigDumbClass bigDumb : oldList) { 
    Wrapper wrap = new Wrapper(bigDumb); 
    if (someCondition()) { 
     wrap.setSelected(true); 
    } 
    wraps.add(wrap); 
} 

理想的情況下,BigDumbClass將實現一個包裝也可以實現一個接口,使包裝推遲所有的呼叫到該實例已包裹。

public class BigDumbClass implements SharedInterface { 
    // All the stuff outlined above 
} 

public class Wrapper implements SharedInterface { 
    // All the stuff outlined above 

    // Methods defined in SharedInterface 
    public void doSomething() { 
     base.doSomething(); 
    } 
} 

否則,您可以爲實例提供getter並直接訪問它。

BigDumbClass base = wrapper.getBase(); 
base.doSomething(); 
+0

僅僅因爲你有一個超類的參考並不意味着你指向一個超類。 'Base baseRef'可能指向SubClass1,因此'SubClass2 subRef =(SubClass2)baseRef'不是有效的強制轉換。 – 2013-04-17 17:54:49

2

有一種方法:各種基於Java Bean規範的操作。

例如:

Commons BeanUtils

for(Base base: list){ 
    SubClass sub = new SubClass(); 
    PropertyUtilsBean.copyProperties(sub, base); 
    if(...){ 
     sub.setSelected(true); 
    } 
    newList.add(sub); 
} 

這部作品根據同名獲取/ setter方法。不復制內部字段。

如果您需要複製內部字段,使用javax.lang.reflect其實並不難。