2013-04-04 49 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其实并不难。