There is a way to solve it, and I used the method in my GUI system.
Type GUI_Object
Field ObjectType
Field ObjectHandle
EndType
ObjectType is a number which defines which type the object is.
ObjectHandle is a pointer to that type.
This is how I create a new object:
ThisGUIObject.GUI_Object = New GUI_Object
ThisText.GUI_Text = New GUI_Text
ThisGUIObject\ObjectType = GUI_OBJECTTYPE_TEXT
ThisGUIObject\ObjectHandle = Handle(ThisText)
Note how ObjectType is set to a constant that tells it that the pointer converted to an int and stored in ObjectHandle is of type TEXT.
And this is a function which returns the entity stored in any one of my types:
Function GUI_GetObjectEntity(ThisGUIObject.GUI_Object)
ObjectType = ThisGUIObject\ObjectType
ObjectHandle = ThisGUIObject\ObjectHandle
Select ObjectType
Case GUI_OBJECTTYPE_DATABAR
ThisDataBar.GUI_DataBar = Object.GUI_DataBar(ObjectHandle)
Avatar = ThisDataBar\Avatar
Case GUI_OBJECTTYPE_DATAARC
ThisDataArc.GUI_DataArc = Object.GUI_DataArc(ObjectHandle)
Avatar = ThisDataArc\Avatar
Case GUI_OBJECTTYPE_TEXT
ThisText.GUI_Text = Object.GUI_Text(ObjectHandle)
Avatar = ThisText\Avatar
Case GUI_OBJECTTYPE_SPRITE
ThisSprite.GUI_Sprite = Object.GUI_Sprite(ObjectHandle)
Avatar = ThisSprite\Avatar
End Select
Return Avatar
End Function
Some of my functions, like "set value" need a case statement in them like this to handle the different object types. Others however, like a function to position the object, just call this function for whatever object is passed to them and then operate on the entity.
It's not perfect but it does allow me to have one set of funcitons to position and set the properties of any GUI object, without having to have all properties that all objects may use contained in one huge type.
Of course, is it worthwhile to muck up your code in this way just so that you don't have one huge type that encapsulates all possible objects? I dunno. It saves ram of course, but most games will have so few objects that it's not even remotely worth concerning yourself about. The types are a little cleaner, but the rest of the code tends to be more difficult to understand because of all the case statements.
And just having all the objects in one type would not get rid of all case statements, because a databar and a dataarc both need different code to execute when their appearance changes, because their meshes are constructed differently. So you'll still have some case statements in there.
All in all, I'm not convinced it was worthwhile to do. It took more time to implement, is more prone to bugs, and doesn't result in simpler, more easily maintained code.
But it made me feel good to get it working at the time anyhow.
The only situation where I could truly reccomend this is a VERY large and complex project, perferably one with more than one programmer working on the same code. For 90% of Blitz games I just don't think there's a significant benefit to using this method... if any benefit at all.