简体   繁体   中英

java, initialize SubClass from SuperClass

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

now i extended the Base Class like:

public class subClass extends Base{
   private boolean selected;

   ...
   getter und setter
   ...
}

i become a list of Base object List<Base>

but i need the same list but as List<SubClass> is there a way to initialize the Subclass from the Base Class?

example:

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

i try to avoid the manual init of each Attribute of the Base Class to the SubClass

i update my Question as requested in the Comments: the Design above is just an example. my QUESTIN EXACTLY IS:

why converting BaseClass into SubClass (sence Subclass extends BaseClass ) is not Possible? why Java dosn't allow me to do the following:

example:

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

then

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

after that the Object sub should have the Attribute Name from the Object b and the title Attribute is null

why is this not the case in java?

sorry for my bad english, thanks

If you have a List<Base> , then you cannot convert it to a List<SubClass> . This is mainly because the list may not contain instances of SubClass . The best you can do is:

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

Generally, however, when you find yourself doing this kind of thing, there's something wrong with your design. You might want to avoid subclassing Base and using composition instead .

EDIT Based on your comments, it sounds like you want to construct a list of SubClass instances using a list of Base instances as a start. One approach is to define a constructor for SubClass that takes a Base as an argument.

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
    ...
}

Then you can construct your new list with:

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

There is a way: Various Java Beans spec based manipulation.

For example:

Commons BeanUtils

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

This works based on get/setters of the same name. Doesn't copy internal fields.

If you needed to copy internal fields, it's actually not that hard to implement using javax.lang.reflect .

You appear to have a class with a lot of attributes and no easy way of setting them all. You have now run in to a problem where you need a class with an additional attribute but you have to deal with that mess of a base class.

I suggest that, instead of creating a subclass and casting, you create a wrapper class around the ugly one:

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
}

Now when you have to create that new list you can wrap everything in the old list

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

Ideally, BigDumbClass would implement an interface that Wrapper could also implement, allowing the wrapper to defer all of the calls to the instance it has wrapped.

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

Otherwise, you can provide a getter to the instance and access it directly.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM