I think you are confused about the distinction between type and class, my friend.
When you instantiate a class, you call the new operator with some constructor. Whatever constructor you pass to the new operator creates an object of the specified *class*. That object is of that class forever until it is garbage collected--objects cannot change their class.
Type, however, is conferred upon an object by the reference that is used to access it. For example, if I write:
I have created an object of class Double, and when I use n to reference it, n confers type Number upon that object. I may have several references to an object:
All of those references reference an object of class Integer. Depending on which reference I use to access that object, one of three types will be conferred upon that object for the duration of that interaction.
So, when you call new BasicMessage(...), you are creating an object of class BasicMessage. Therefore, references to it can only confer upon that object types that are compatible with BasicMessage...that's why you're getting a ClassCastException.
Fortunately, I think reflection can solve your problem. Each class that dumps its contents to a raw byte stream is going to have to put into that stream its class name (getClass().getName()). Then, when you read back from that byte stream, you'll have to read that class name out from the beginning of the stream and create the instance this way:
Now, when you hand that class back to callers, they'll be able to cast down to any type associated with the class name encoded at the head of the stream because the newInstance() method creates an object of the appropriate class. Before, you were creating an object of class BasicMessage, which is not what you wanted.
This is probably the most elegant solution to your problem, but it's still not very satisfying. I would say this kind of monkeying around indicates that your design could be better. The problem you're having has to do with the loss of type information. Whenever you dump an object's content into a raw byte stream, you're losing all of the type information that OO depends upon. I would think about how to redesign your entire system so that you never have to lose type information in the first place, because with it goes all the advantages of OO and to get them back you have to do things like what I've suggested--marshal up the type information into raw bytes and decode it on the other end.
You might be able to write your own stream or use one of the existing streams in the JDK to do this.
Java does provide support for reading and writing objects and serialization and all that good stuff...maybe your truly elegant solution lies therein.
sev
[ April 09, 2004: Message edited by: sever oon ]