java, initialize SubClass from SuperClass
Asked Answered
M

3

14
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

Management answered 4/4, 2013 at 4:2 Comment(7)
Initialize subclass from superclass -- why? This sounds ill conceived at best and dangerous at worst.Decosta
Where is the List<Base> field defined? In the Base class itself? Do you have control over where its declared and how its initialized?Affixation
I highly suggest you look into "prefer Composition over inheritence"--google it. You will find some interesting discussions on the matter. I only say this because it looks like you are attempting desperately to abuse the privilege.Bonnie
How can you avoid the manual initialization of the Base class attributes if Base has no constructor or initialization method? Are you attempting to convert a Base class in to a Sub class?Piccaninny
yes @Jake, thats exactly what i am trying to doManagement
@Perception, there is a DB-Controller which provides a Methode like getList() return List<Base>. i have no controll over this Class. my Question is to understand why Java dosn'T allow me converting BaseClass into Subclass. i think, if i do: SubClass sub = base; sub should have all attributes of base, and the rest attributes in SubClass which not in Base class could be null. why is that not possible? thats what i am trying to understand?Management
@Management - good and helpful details, you might want to edit your question to include them. Unfortunately, you are SoL, since the list already contains instances of Base objects. Remember that a SubClass may be a Base, but a Base is not necessarily a SubClass. You could hack the list, replacing each Base object with a SubClass object, with its state cloned from Base, but that would be an ugly and bad thing to do.Affixation
F
7

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);
}
Flyleaf answered 4/4, 2013 at 4:5 Comment(4)
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?Management
i mean, after casting SubClass should have all attributes of the Base Class and the rest Attributes in SubClass would be nullManagement
@Management - Okay, your comments clarified to me something about what you want. I revised my answer to address this.Flyleaf
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.Management
L
3

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.

Lush answered 23/6, 2013 at 9:48 Comment(0)
P
2

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();
Piccaninny answered 4/4, 2013 at 4:55 Comment(1)
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.Piccaninny

© 2022 - 2024 — McMap. All rights reserved.