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(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
属性为空
为什么在java中不是这种情况?
抱歉我的英语不好, 感谢答案 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的规范操作。
例如:
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();