- Home /
Forcing a type conversion from an abstract class C#
I have a class of objects in an object pool that are all derived from an abstract class, but this is failing:
//SUProjectile : Base abstract class
//BeamProjectile : derived from SUProjectile
SUProjectile SU_P;
GameObject goProjectile = TheObjectPool.GetNextObject("Heretic Juice");
System.Type st = GetProjectileType("Heretic Juice");
SU_P = (st) goProjectile.GetComponent(typeof(st)); //<-- fail, can't use "st" in this way apparently..
This is, of course just part of the problem.
I have an objectpool, it stores many types of projectiles all derived from the base abstract class of SUProjectile. There may be hundreds of projectile types eventually, so I'd like to do this at runtime..
Without trying to run it through a compiler, is it not that you already have the typeof in st? typeof st would just be System.Type, no?
Although would it not be easier to use the generic version of GetComponent with the base type? I think this sort of structure suggests you don't really need the "correct" type, just the instance? Unless the next few lines are a switch(st) or something, which it probably a symptom of a bigger problem...
SU_P = goProjectile.GetComponent< SUProjectile > () ;
I think you want to do GetType at the end
SU_P = (st) goProjectile.GetComponent(typeof(st)).GetType();
I tried this but it wasn't working.. apparently due to another uncaught bug.. But this works. thanks. if you put it as an answer i can accept and close the q.
Answer by Tarlius · Oct 24, 2013 at 08:51 AM
I think it would be easier to simply use the generic version of GetComponent with the base type:
SU_P = goProjectile.GetComponent< SUProjectile > ();
Answer by fafase · Oct 24, 2013 at 09:24 AM
You do not need the GameObject in the middle.
Simply:
SUProjectile SU_P;
SU_P = TheObjectPool.GetNextObject("Heretic Juice");
if all objects inherits from SUProjectile, they are all of this type so they can directly be stored into an object of type SUProjectile.
Then if you are trying to access a method from the SUProjectile you can call it, if you need to access something from a sub class you can try:
if(SU_P is SubClass){
SubClass sub = (SubClass)SU_P;
sub.SubMethod();
}
I appreciate the response. GetNextObject returns a GameObject ref, as I am never sure which child-SUProjectile the object pool may be storing. Also, I'm trying to avoid having to do checks if it is a subclass.. as I will be adding many types over time, I'd rather only make changes in one place....
If your object pool is filled with object derivating from the same base class there is little reason why it should return a GameObject. Just by returning the appropriate type, you would make it easier. That is the whole point about C#, typesafe.
Not to mention slightly faster ;) I considered mentioning it myself, but thought it wasn't really related to the question.
You can have a pool of game objects even when you only store references to one of their components. For example, you could have a pool of SUProjectile
. Every one of them would include the whole game object, and you wouldn't need to be using the slow GetComponent
every time.
Also, if you plan to add other subtypes that inherit from SUProjectile
, it will keep on working.
If what you want is to have the One Pool that pools objects of many different types, maybe you could design something different.
What about a class like
class TheOnePool
{
protected Dictionary<Type, ArrayList> megaPool;
public T GetNext<T>()
{
var type = typeof(T);
if(megaPool.Contains$$anonymous$$ey(type))
{
var thisTypePool = megaPool[type];
var nextObject = thisTypePool[thisTypePool.Count-1] as T;
// Deal here with the case that this type pool is empty and needs to spawn new blank objects
thisTypePool.RemoveAt(thisTypePool.Count-1);
return nextObject;
}
}
public TheOnePool(params Type[] types)
{
// Initialize the pools for every time to the starting desired size
megaPool = new Dictionary<Type, ArrayList>();
foreach(Type type in types)
{
megaPool.Add(type, new ArrayList());
// Add here some blank pooled objects of this type to this pool if you want
}
}
}
And you could initialize it like this.
new TheOnePool(typeof(SUProjectile), typeof(Enemy), typeof(TreeScenery), typeof(Rock));
And you would get next pooled object like this.
var nextObject = theOnePool.GetNext<SUProjectile>();
Answer by Azrapse · Oct 24, 2013 at 10:52 AM
In line 6 you get the Type
in st
. An object of type Type
is an object with information about a type in C#.
In line 7 you do weird stuff.
First you call the method GetComponent
passing as parameter not st
, but typeof(st)
. What typeof()
does is returning a Type object with information about the type of the parameter. In this case the parameter of typeof(st)
is st
, that is of type Type
. So the typeof()
call is returning a Type
object with information about class Type
(Yes, you have made there a superconfusing tonguetwister in C#. :D )
Then you try to cast the returning value into (st)
, but st
isn't a type, but an object of type Type
, that is, an object with information about a type. So the compiler doesn't let you. You cannot cast to an object, only to a type.
What the last line should look like is
SU_P = (SUProjectile) goProjectile.GetComponent(st);
Line 7 is actually the long form of
`someGameObject.GetComponent<someComponent>()..`
I tried all variations, using typeof(st), etc, but nothing worked. SU_P = (SUProjectile)tmpGO.GetComponent( st ); also doesn't compile... But appreciate trying.
I was able to compile it without any problem. But its a weird case ;)
Code I used:
$$anonymous$$onoBehaviour mb;
GameObject go = null;
System.Type st = typeof($$anonymous$$onoBehaviour);
mb = ($$anonymous$$onoBehaviour) go.GetComponent(st);
I cannot really see why it wouldn't compile. If SU_P is of SUProjectile type, and st is of Type type, all type requirements are met. The compiler error must be elsewhere.
Your answer
Follow this Question
Related Questions
Easy? Convert System.Type to UnityEngine.Component 3 Answers
What's the difference between GetComponent and GetComponent(StringName)? 1 Answer
Getting all component types (even those not on the scene) 1 Answer
Declare Component type in GetComponent 2 Answers
Reference to Scene Object Component in Prefab Editor, 'Type Mismatch'? 1 Answer