Bug or no? Reflection looses track of dervied type

BlitzMax Forums/BlitzMax Programming/Bug or no? Reflection looses track of dervied type

USNavyFish(Posted 2009) [#1]
I've got a base type, TForm, with code in it's New() constructor method.

The derived type TMainApp extends TForm. When I create a new 'TMainApp', the base type's constructor is called, since TMainApp does not elaborate upon the constructor method by defining its own.

The base's constructor includes the following troublesome code:

Local FormType:TTypeId = TTypeId.ForObject(Self) 			


The problem is that TTypeId.ForObject(Self) returns the BASE class, and NOT the derived class.

Keep in mind that although New() is defined in the base class, it is called by the line "MainApp:TMainApp = New TMainApp". So the calling object is most definitely of the derived type.

Of course, if I elaborate upon the New() method within the derived class and include the same code, TTypeID.ForObject(Self) returns the correct (derived) type. But having to write out a constructor method for each derived type kinda defeats the purpose of inheritance in the first place!

Is this a bug or expected behavior?


N(Posted 2009) [#2]
I'm going to take a wild guess and say this is probably because the class of the object is set like so:
Function Foo_New(obj)
	obj.class = bbFooClass
	
	' your remaining constructor code
End Function

Function Bar_New(obj)
	Foo_New(obj)
	obj.class = bbBarClass
	
	' your code
End Function

Function Baz_New(obj)
	Bar_New(obj)
	obj.class = bbBazClass
	
	' finally, your code
End Function


For reference, that sort of layout would fit this code:
Strict

Type Foo
	Method New()
		Local id:TTypeId = TTypeId.ForObject(Self)
		Print "Foo: "+id.Name()
	End Method
End Type

Type Bar Extends Foo
	Method New()
		Local id:TTypeId = TTypeId.ForObject(Self)
		Print "Bar: "+id.Name()
	End Method
End Type

Type Baz Extends Bar
	Method New()
		Local id:TTypeId = TTypeId.ForObject(Self)
		Print "Baz: "+id.Name()
	End Method
End Type

New Baz


The constructors are called in sequence, and the classes are set in sequence. Again, this is a guess, but it makes sense to me. Edit: Also, if this is the case, it's most certainly not a bug.

Edit 2: Looking at the ASM, I think I'm right.


USNavyFish(Posted 2009) [#3]
Thanks for the reply. All of this would be simplified if I had a way of dynamically casting objects using a 'variable' cast type. For example, grabbing a TTypeID and using that to cast objects.

Your example answered it, however: The implementation is not a bug. Too bad really :)


N(Posted 2009) [#4]
If in doubt, try adding an Init method that does whatever you need to and then returns self. That way, you can do something like `Local f:Foobar = New Foobar.Init()` with the same end result.


USNavyFish(Posted 2009) [#5]
Yes. I wanted to have code stored in the base class for a 'template' type, so that another user could easily extend the base class without having to worry about configuring the derived types. I was able to accomplish this by defining a registration function in the base type which takes as a parameter an object of the base class. The user must simply call the registration function once every time he creates an instance of any derived type and pass to that function the new instance. The reason this works is that even though the parameter type for the registration function is of the base class, TTypeID.ForObject within that function returns the proper derived class and allows me to pick the extended class' methods and fields. So Reflection doesn't loose track of a derived type, even if the pointer being TTypeID'd is improperly cast!