java, initialize SubClass from SuperClass

23,794

Solution 1

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

Solution 2

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.

Solution 3

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();
Share:
23,794
Rami.Q
Author by

Rami.Q

Updated on July 09, 2022

Comments

  • Rami.Q
    Rami.Q almost 2 years
    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

  • Rami.Q
    Rami.Q about 11 years
    thanks for the answer. the List has only Objects type of Base, so these are no instances of Subclass in the list. but why casting the Class is wrong? attributes in the SubClass could be null after casting, the i can set it manualy like in my example above. what do you tink about that?
  • Rami.Q
    Rami.Q about 11 years
    i mean, after casting SubClass should have all attributes of the Base Class and the rest Attributes in SubClass would be null
  • Ted Hopp
    Ted Hopp about 11 years
    @Rami.Q - Okay, your comments clarified to me something about what you want. I revised my answer to address this.
  • Rami.Q
    Rami.Q about 11 years
    thanks for your answer. i accepted it, because i do it this way. but its still not the best solution. Oracle should give us an auto Conversion from Base Class into SubClass. something like Attributes UNION.
  • Jake Greene
    Jake Greene about 11 years
    Just because you have a reference for a super class does not mean you are pointing to a super class. 'Base baseRef' may be pointing to a SubClass1, so 'SubClass2 subRef = (SubClass2)baseRef' is not a valid cast.