C# Typecasting problem with T2DSceneObject
by Laurence Grant · in Torque X 2D · 01/08/2007 (11:05 am) · 5 replies
Hey guys, I'm not a C# guy, and just learning the basics as I play with TGBX. Maybe this is the wrong forum, but since it's the main area for C# and Torque development, I thought I'd start here.
Anyway, I have a class that extends T2DSceneObject like this:
public class _3DSceneObject : T2DSceneObject
{
float x = 0.0f;
float y = 0.0f;
float z = 0.0f;
.. methods here
}
Then I copied some original code which looked like this,
T2DSceneObject _ball = (T2DSceneObject)(TorqueObjectDatabase.Instance.FindObject("BBall") as T2DStaticSprite).Clone();
and modified it to this
_3DSceneObject _ball = (_3DSceneObject)(TorqueObjectDatabase.Instance.FindObject("BBall") as T2DStaticSprite).Clone();
Now it's complaining that it can't type case from T2DStaticSprite to _3DSceneObject. I thought since _3DSceneObject was extending T2DSceneObject, I should be able to do this. I also assumed the T2DStaticSprite was a subtype of T2DSceneObject, but then I noticed T2DStaticSprite actually extends T2DSceneObject, the opposite of what I originally thought. I tried changing my class to extend T2DStaticSprite, but I still get the same typecasting error. Any suggestions would be greatly appreciated.
Thanks
Anyway, I have a class that extends T2DSceneObject like this:
public class _3DSceneObject : T2DSceneObject
{
float x = 0.0f;
float y = 0.0f;
float z = 0.0f;
.. methods here
}
Then I copied some original code which looked like this,
T2DSceneObject _ball = (T2DSceneObject)(TorqueObjectDatabase.Instance.FindObject("BBall") as T2DStaticSprite).Clone();
and modified it to this
_3DSceneObject _ball = (_3DSceneObject)(TorqueObjectDatabase.Instance.FindObject("BBall") as T2DStaticSprite).Clone();
Now it's complaining that it can't type case from T2DStaticSprite to _3DSceneObject. I thought since _3DSceneObject was extending T2DSceneObject, I should be able to do this. I also assumed the T2DStaticSprite was a subtype of T2DSceneObject, but then I noticed T2DStaticSprite actually extends T2DSceneObject, the opposite of what I originally thought. I tried changing my class to extend T2DStaticSprite, but I still get the same typecasting error. Any suggestions would be greatly appreciated.
Thanks
#2
01/08/2007 (6:06 pm)
Also, _3DSceneObject "is a" T2DSceneObject. T2DStaticSprite "is a" T2DSceneObject. But _3DSceneObject "IS NOT A" T2DStaticSprite. So in addition to the "wrong way" casting you're doing, _3DSceneObject has no business getting anywhere near a T2DStaticSprite reference.
#3
Brian, I understand that neither T2DSceneObject nor T2DStaticSprite have the additional fields that _3DSceneObject has, but all the additional data is defined in the constructor. I thought this was a common sort of practice, to extend class, but if I can't initialize the base class its a problem.
I know I could just create an attribute of type T2DSceneObject in _3DSceneObject, but then the interface changes, and I wanted to keep it as transparent as possible.
I guess it makes sense that what I'm doing is backwards, but it just seems to me like it's something that you should be able to do.
If anyone else has any more suggestions I'd be happy to hear them.
01/08/2007 (7:34 pm)
Ben, I've tried creating _3DSceneObject to extend both T2DSceneObject and T2DStaticSprite, with the same results.Brian, I understand that neither T2DSceneObject nor T2DStaticSprite have the additional fields that _3DSceneObject has, but all the additional data is defined in the constructor. I thought this was a common sort of practice, to extend class, but if I can't initialize the base class its a problem.
I know I could just create an attribute of type T2DSceneObject in _3DSceneObject, but then the interface changes, and I wanted to keep it as transparent as possible.
I guess it makes sense that what I'm doing is backwards, but it just seems to me like it's something that you should be able to do.
If anyone else has any more suggestions I'd be happy to hear them.
#4
Semantically you could say that A represents humans and B represents men and C women. Men and women are a subclass of humans, but you run into problems when you try to convert a man into a woman or vice versa. You might be able to force a conversion but things are going to get ugly at that point.
This was why I mentioned you might be able to provide an explicit cast function so that the cast from T2DStaticSprite to _3dSceneObject was handled by hand by you, but you would have to create data out of nothingess to fill in the fields for your class and throw out information that relates to the sprite.
01/08/2007 (8:22 pm)
The problem you have is that you have this situationA
/ \
B CBoth B and C inherit from class A. You are trying to cast an object of class B to class C which is not something I have ever seen supported by polymorphism or inheritence. Semantically you could say that A represents humans and B represents men and C women. Men and women are a subclass of humans, but you run into problems when you try to convert a man into a woman or vice versa. You might be able to force a conversion but things are going to get ugly at that point.
This was why I mentioned you might be able to provide an explicit cast function so that the cast from T2DStaticSprite to _3dSceneObject was handled by hand by you, but you would have to create data out of nothingess to fill in the fields for your class and throw out information that relates to the sprite.
#5
If you want it to have static sprite qualities and render as a static sprite, you'll need your class to be derived from static sprite and not scene object (unless you're a masochist and want to rewrite all the render code).
If you don't want to render it as a static sprite then I have to ask, why are you creating it from a static sprite instance? Exactly what is this _3DSceneObject supposed to do?
Also, for the sake of being perfectly clear, you actually *can* cast an object that's being stored in a parent reference to a child object reference. You can't store a reference in a field that is a reference of a different type (i.e. miscast), and you can't cast an object to a type that the object itself is not an instance of or derived from (you can, but you'll get a null reference).
For example...
01/09/2007 (4:09 am)
Good replies. One way to do the "cast" that Brian is talking about would be to create a _3DSceneObject constructor that takes a StaticSprite as an argument. In that constructor you would basically copy all the field values over to the new object and populate the _3DSceneObject fields however you want, because as Brian said, you would be creating data out of 'nothingness'.If you want it to have static sprite qualities and render as a static sprite, you'll need your class to be derived from static sprite and not scene object (unless you're a masochist and want to rewrite all the render code).
If you don't want to render it as a static sprite then I have to ask, why are you creating it from a static sprite instance? Exactly what is this _3DSceneObject supposed to do?
Also, for the sake of being perfectly clear, you actually *can* cast an object that's being stored in a parent reference to a child object reference. You can't store a reference in a field that is a reference of a different type (i.e. miscast), and you can't cast an object to a type that the object itself is not an instance of or derived from (you can, but you'll get a null reference).
For example...
// in this case, _3DSceneObject is derived from T2DSceneObject T2DSceneObject SORef; T2DStaticSprite SpriteRef; _3DSceneObject MyRef; // this is valid - creata a static sprite instance and store // it in a static sprite reference SpriteRef = new T2DStaticSprite(); // so are these - cast the object to a T2DSceneObject and store // that in a T2DSceneObject reference SORef = SpriteRef as T2DSceneObject; SORef = (T2DSceneObject) SpriteRef; // these will result in 'null' because the object itself is not // a _3DSceneObject, nor is it derived from _3DSceneObject // HOWEVER, will not result in an error MyRef = SpriteRef as _3DSceneObject; // this will result in an error // trying to store a T2DStaticSprite in a T2DSceneObject reference without casting SORef = SpriteRef; // so will this MyRef = (T2DSceneObject) SpriteRef;
Torque Owner Brian Doig