dynamic typecasting for re-usability

Hi there,

I'm trying to dynamically cast an object to a class only known at runtime. All that is known at compile time is the name and type of a variable inside the object - and that is all that is of interest. The reason for this is to create re-usable code to allow multiple classes to be used as peers (all owned by the unknown class) together.

I have a method (provided, so I can't change it) getOwner() that gives me the parent class, but as type Object. I need to re-cast it to the correct class to be able to access its content. I know ahead of time that the variableknownvar will exist in the parent class, and I know what type it will be.

So instead of doing:

if(this.getOwner().getType() =="ClassA")

{

(ClassA)this.getOwner().knownvar = somevalue;

}

elseif(this.getOwner().getType() =="ClassB")

{

(ClassB)this.getOwner().knownvar = somevalue;

}

elseif ... (ad nauseum)

I'd rather like to do something similar to this (this does not work):

(this.getOwner().getType())this.getOwner().knownvar = somevalue;

In fact, I'd prefer not to do the whole list of elseifs if at all possible, since it limits possible future use to pre-thought of class names - and adding some that might not exist (also bad).

Any suggestions on how this can be done?

[1620 byte] By [Elrina] at [2007-10-3 3:35:37]
# 1

why do you have to cast? that's not object-oriented.

not knowing the true runtime type is the essence of polymorphism. if you can refactor the common behavior into an interface, you can get different runtime behavior without casting. i think that should be the goal.

"if" checks to establish type is a sure sign that you aren't thinking about objects properly.

%

duffymoa at 2007-7-14 21:30:22 > top of Java-index,Java Essentials,Java Programming...
# 2

If you really, really can't edit the source providing "Object getOwner()" to return an interface expressing the presence of a mutable property "knownvar", you are left with using reflection:

Object object = this.getOwner();

Class clazz = object.getClass();

Field knownVar = clazz.getField("knownvar");

//if it is not public: knownVar.setAccessible(true);

knownVar.set(object, somevalue);

But seriously, if all those classes expose a field "knownvar" and other parts of the program need to be aware of this, it should really be expressed by an interface (and probably an abstract class) containing a method setKnownVar, implemented by all classes ClassA, ClassB, ... so you can just do

HasMutableKnownVar object = this.getOwner();

object.setKnownVar(somevalue);

I know you said you can't change the signature and implementation of getOwner(), but actually the current design is incompatible with the need to know about those classes all having a field "knownvar". Reflection in this case is a workaround to use this commonality without it being expressed properly in the "owner" classes. It's bad design, but you can get around it.

Lokoa at 2007-7-14 21:30:22 > top of Java-index,Java Essentials,Java Programming...
# 3

Thank you for the replies! (Especially Loko for that possible workaround)

Yes indeed, it is quite a bad design and I flinch at having to hack things so badly. It is not a clean and elegant design when done like this. Unfortunately I have no choice but to use a workaround. I'll try your suggestion and see if it can do the trick.

duffymo - As for using if checks - that is exactly what I don't want to use exactly because it is not object oriented - but is a way to express and explain to others what kind of function I am trying to perform. I'd perfer to use something like my second code snippet where no prior knowledge of the class is needed. I need to cast, otherwise the knownvar property is not accessable. Unfortunately, like I said, I do not have control over the interface, so I need a workaround.

There is also a small chance I might be able to convince the supplier of the owner class to implement this better by using an intermediate class that extends the one providing "Object getOwner()", returning a more specific class that expresses the presense of knownvar. I am using Java code fragments inside a third-party product, so it might not be possible to make this change within the timescales available.

Elrina at 2007-7-14 21:30:22 > top of Java-index,Java Essentials,Java Programming...
# 4
at least limit the damage and put that awful code in a factory. that way you won't have to pollute the rest of your stuff with it.%
duffymoa at 2007-7-14 21:30:22 > top of Java-index,Java Essentials,Java Programming...