java,从SuperClass初始化SubClass

时间:2013-04-04 04:02:31

标签: java initialization subclass superclass extends

public class Base {
  //long list of attributes
  // no Constructor using fields
  // no init methode 
  // i cannot change this class
}

现在我将基类扩展为:

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);
}

我尽量避免将Base Class的每个属性手动初始化为SubClass

我按照评论中的要求更新我的问题: 上面的设计只是一个例子。我的QUESTIN确实是:

为什么将BaseClass转换为SubClass(s​​ence 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属性为空

为什么在java中不是这种情况?

抱歉我的英语不好, 感谢

3 个答案:

答案 0 :(得分:7)

如果您有List<Base>,则无法将其转换为List<SubClass>。这主要是因为列表可能不包含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

编辑根据您的评论,您似乎想要使用SubClass个实例列表作为开头构建Base实例列表。一种方法是为SubClass定义一个以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);
}

答案 1 :(得分:3)

有一种方法:各种基于Java Bean的规范操作。

例如:

Commons BeanUtils

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

这基于同名的get / setters。不复制内部字段。

如果您需要复制内部字段,使用javax.lang.reflect实现起来并不困难。

答案 2 :(得分: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将实现Wrapper也可以实现的接口,允许包装器将所有调用推迟到它已包装的实例。

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();