Reflection and name().

BlitzMax Forums/BlitzMax Beginners Area/Reflection and name().

tonyg(Posted 2008) [#1]
How can you use the type name returned from ttypeid name() method to cast an object back to it's original type?
SuperStrict
Type ttest
   Field x:Int
End Type

Local test1:ttest=New ttest
test1.x=5
Local test2:Object=Object(test1)


Local id:TTypeId=TTypeId.ForObject(test2)
Local typename:String=id.name()
Print typename
'Print typename(test2).x

Obviously this is much simplified but I have my original type name in a string variable called 'typename'.
Unfortunately, I can't use that to cast my original object. If you uncomment the print statement you get message
'Expression of string cannot be invoked'
Am I missing something?


Azathoth(Posted 2008) [#2]
If you're using reflection why do you need to cast? Reflection already allows you to access members.

Edit: Casting implies you have an idea what the type should be.


tonyg(Posted 2008) [#3]
How would I do that? In my example, how would I print the value of x for my object?
In addition, by casting back to the original object type I can then use all my existing function/method calls which rely on that type.
Or am I missing something?

<edit>
Yep, I thought I could get a VERY good idea what the type is by using reflection and then casting.


Jake L.(Posted 2008) [#4]
For fld:TField=eachin id.EnumFields()
   if fld.TypeID().Name()="Int" then fld.SetInt(test2,42)
next


Of course this works without EnumFields, but I'm at work, so I can't lookup how to get the field without it. Once you have a TField and a valid object, you can use the various Set... methods.


tonyg(Posted 2008) [#5]
Ok, I must really be missing something then.
Using reflection I can get the original type and supertype of an object as a string variable. I can also get all the fields, functions and methods of that class.
However, once I have used reflection to get that information I have to keep using the reflection types to access the information unless I use them in select/case or if/end the type back to it's original type?


Jake L.(Posted 2008) [#6]
Hmm, maybe I don't understand your question/problem. I thought you're looking for a way to set a field's value - that's what the code does.


tonyg(Posted 2008) [#7]
I probably oversimplified the code I posted. Basically, I am looking for the best method to find out an objects type and cast back to it.
I thought I could use reflection to get the typename and then use that to cast the object. This would avoided using select/case or if/endif statements.


Jake L.(Posted 2008) [#8]
Ah, understand. I guess it's impossible, but maybe someone can proove me wrong, I'm interested in this, too.


Dreamora(Posted 2008) [#9]
Reflection will only get you the type name and allow you to create an instance of that type.
it will not automagically cast anything.

So with the TTypeID.Name() you need to use a Switch and cast it accordingly.

question is what you really want to do with that and why you death cast it (-> to object) instead of a common type that you are going to use, as I do not believe that there is a reason to cast it down to object as only "familiar" class instances are pushed into the same functionality.


tonyg(Posted 2008) [#10]
question is what you really want to do with that and why you death cast it (-> to object) instead of a common type that you are going to use, as I do not believe that there is a reason to cast it down to object as only "familiar" class instances are pushed into the same functionality.


I don't push it down to object or 'death cast' it. Bmax does when it returns an object from the TLink value method.
Maybe my oversimplified code has confused you.


Koriolis(Posted 2008) [#11]
The thing is, it really doesn't makes sense at all. You have to consider that BlitzMax is a statically typed language. This means in particular that you can't call a method if you don't know at compile time which method to call (as opposed to what would happen in dynamicly typed languages where you could call anything you want, and the runtime would figure if the method actually exists or not - and fail if not).

(NOTE: The only dynamic part is that you may have overriden the method, and which version amongst all the overriden methods is decided at runtime. But the compiler still needs to know the method (as declared in the top most type that declares it)).

Given that we're dealing with a statically typed language:
- either you know the method in advance (at compile time), which implies that you knwo the type already. In this case you should use a simple cast in the first palce
- either you discover the type at runtime via reflection, but then the object you're working on is practically untyped (more precisely, it's known simply as being an instance of "Object", you can't tell much more at compile time). This means you may only call methods in the "Object" type.

So yes, if you discover a method at runtime via reflection, you'll have to use reflection too if you want to call it.


Dreamora(Posted 2008) [#12]
even if TList gives a object back you still can cast it to your "basic type" that is held within that list. thats actually no problem.


tonyg(Posted 2008) [#13]
OK, I'll bite : What do you mean by 'basic type'.
Are you suggesting that objects on a list should all be off the same type or extended from the same type?


Dreamora(Posted 2008) [#14]
Extending from the same basic type.

I don't assume that you (as realworld example) would store car, turnips and pens in the same list. you would have a lit for vegetables, for vehicles and one for pens of all kind and then extend turnip from vegetable, car from vehicle and any pen type you use from pen.

Now you can implement basic functionality on those base type that those kind of things have and that stuff you don't implement but that must be present can still pe put in as method xyz() Abstract so extending types must implement it.

that way you can just cast to the base type in the for ... = eachin list part instead of using a select case structure to do "individual casting" that might not even be needed.

But this might depend on what you want to achieve.

A simple example of such a thing is Entity in Blitz3D for example ... they all extend from it and share the "base featuerset" ie entity commands


tonyg(Posted 2008) [#15]
I don't understand : Why would I not have pens and turnips on the same list? What about a shopping list , RPG Inventory, Objects on a tile etc? On that I might have :
Knife extends TWeapon
Turnip extends TVegetable
Pen extends TWriting_Implements.
OK, it might be better to TWeapon with a field TSpec which extends to TKnife_spec but, for my question, that is all irrelevant.
The basic question was 'Can I use Reflection to cast?'
The answer appears to be 'no, not directly' so I am happy with that.


Dreamora(Posted 2008) [#16]
In an inventory you would store TItem most likely, wouldn't you? (or from java end TStorable, no mather if inventory or box or whatever)

In BM, a usefull and clever class design etc is more than only decoration. If you don't have it you won't stand a chance getting it implemented bug and head ache free as the imports etc will start to get ugly clustered etc. The final result is degraded performance in worst case even slower than Blitz3D

Thats why I pointed that one out.


Czar Flavius(Posted 2008) [#17]
Could you explain more what you are suggesting please?


Dreamora(Posted 2008) [#18]
well a class TItem that holds the basic functionality you might need for any item + a method that returns the type of the item as integer (for fast select or straight usage as array index)

for example you could have a method use() abstract as all items are used in a way and the extended types implement that each in its own way. pen would write something, turnip would heal or grant "stuffed" attribute, a knife would cut or attack ...
this kind of stuff.

think first of the "common" class and then think about the specialisted extended classes that the player actually will "see" (in an rpg for example)