开发者

Java = What are alternatives / solutions to downcasting?

I have Value-Objects/Beans (only containing members, no 开发者_开发百科logic):

public class Parent {
String first;
String second;
}

Some processing logic returns the "Parent". I then do some further processing and want to add furtehr fields:

public class ParentAddedMembers extends Parent {
String third;
String fourth;
} 

The Problem is, I can NOT downcast from Parent to ParentAddedMembers.

ParentAddedMembers parentAddedMembers = (ParentAddedMembers) parent;

This seems to be invalid.

(From my point of view in this case it would be legal, when downcasting the unassigned, new fields would simply hold nulls. But it seems java does not allow this).

What is the correct solution, if I do not want to copy all fields manually (I could write a copy method that copies the Parent members to a newly created ParentAddedMembers. But this does not work for private fields. Furthermore it will break very easyly if I add/delete membes in parent...)

What is the corret solution for this?

Thanks very much!

Markus

Update: What I want to achive is. I have a thirdparty Library that returns some Objects Parent (from a search result), but I need to add further fields (metadata) to it. Downcasting, as described would solve the problem easily but does not work. I also can not change the parent as it is from a third party lib.


(From my point of view in this case it would be legal, when downcasting the unassigned, new fields would simply hold nulls. But it seems java does not allow this).

This only makes sense intuitively because the fields in Parent and ParentAddedMembers have the same names for the fields. You say yourself that having a copy constructor is error prone due to modifications to the fields. Wouldn't such casting capabilities be too? (What if you change Parent.first to Parent.param1.)

Bottom line is that Java disallows this, because it doesn't make sense in other cases. You can't cast a Vehicle into a Car. (The Vehicle object may be a Bike.)

What is the corret solution for this?

  • One option would be to simply do

    public class Parent {
        String first;
        String second;
    
        boolean extended;
        String third;
        String fourth;
    }
    
  • or, to go the route you explain and do a copy constructor.

  • You could also solve it using reflection. Then you would be able to loop through all fields of Parent and assign the fields of ParentAddedMembers based on the field names. (But using reflection indicates some code smell actually.)


Forget about it, and try to understand polymorphism and how it can help you in this regard.

[edited after a downvote]

Whoever downvoted me, you might not like my wordings. But please try to understand what I said. It may be blur but it means don't do it this way, and make use of polymorphism instead. Have a getter() and setter(), use polymorphism and avoid the cast altogether.

[edited after question update]

Then, you should consider looking into Adapter Pattern.


You could write a constructor for ParentAddedMembes so that the constructor would take a Parent object as parameter and populate itself with the Parent's data.

Something like this:

public ParentAddedMembes(Parent parent) {
    // populate
}

And then later

ParentAddedMembes parentAddedMembes = new ParentAddedMembes(parent);


Strange, as your code is valid. My guess is that variable of type Parent is not holding a value that is a ParentAddedMembes.

Parent parent = new ParentAddedMembes();
ParentAddedMembes pm = (ParentAddedMembes) parent;

The above code is valid. You can, however, use instanceof keyword to do your downcasting. e.g

Parent parent = new ParentAddedMembes();

if (parent instanceof ParentAddedMembes)
    ParentAddedMembes pm = (ParentAddedMembes) parent;

This is to check if parent is of a ParentAddedMembes.


Use constructor.

Parent(Parent p) {
// initalize it
}

ParentAddedMembes(Parent p) {
   super(p);
   // By default, fields are null
}


I'm not saying it is always the case, but this could indicate a design flaw, if you need to access the object as a child type why is it being referenced as the parent type.

However, to answer your question, wrap the cast in an if instanceof


"The Problem is, I can NOT downcast from Parent to ParentAddedMembers"

The problem is, you want not DOWNcast. You want UPcast :)


Something you can do, when you want to use members of the extension, to check type and THEN cast:

if(variable instanceof ParentAddressMembers) {
  ParentAddressMembers pam = (ParentAddressMembers)variable;
  // you can access pam.third and pam.forth here.
} else {
 // you can't acces pam.third and pam.forth so better not to bother them.
}

After reading your Update I add this: However, it's not a very good idea to extend third party classes as the base class may badly interfere with your extension. (Base API changes, use of reflection, dynamic proxy, etc.) It's better to make a wrapper class which contains the originally returned 3rd party object AS IS, and your plus fields.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜