Instance of?

BlitzMax Forums/BlitzMax Programming/Instance of?

TheTophatDemon(Posted 2014) [#1]
OK, I haven't touched this language in a while, so I've got a stupid little question for you.
Is it possible to check if an object is an instance of a type?
Like, if you have a function that returns an entity, and you need to find out if it's an enemy or not.
I already have a workaround for this problem, but I just wanted to know if there was a faster way.


Yasha(Posted 2014) [#2]
You can try to downcast to the desired type. If the object isn't an instance of that type, it will return Null (similar to C#'s `as`).


Derron(Posted 2014) [#3]
I think you mean upcast.

type entity
type figure extends entity
type enemy extends figure
type player extends figure


Type entity:
method onCollide(e:entity)
print "entity collided with entity"
end method


type figure:
method onCollide(e:entity)
if figure(e) then print "figure collided with figure"
Super.onCollide(e)
end method


type enemy:
method onCollide(e:entity)
if enemy(e) then print "enemy collided with enemy, yay...boring"
if player(e) then print "enemy collided with player, Yummy."

Super.onCollide(e)
end method



Because all extended types base on one class, you can always downcast them (even downcasted, they use methods the extending type has overriden - so an entity(player).onCollide(e) will still run the onCollide() defined in the player-type).

Upcasting instead das only work if the object is made of the given type (or again extended from it).

In our example figures can use entity+figure, player can use entity+figure+player and so on .



bye
Ron


Yasha(Posted 2014) [#4]
See here: http://en.m.wikipedia.org/wiki/Downcasting

"Down" = away from Object
"Up" = towards Object

The term "upcasting" is rarely used, since it's implicit, and guaranteed to work; all casts you would actually want to write (or check) will be downward.


Yan(Posted 2014) [#5]
How very Swiftian


Derron(Posted 2014) [#6]
According wikipedia you are right ... I followed the assumption that "downcasting" means casting down the hierarchy until you reach the basement (like peeling of layers) - but seems it is the opposite direction.


Do you have a "etymological" explanation why it is this way? Maybe because in an UML you display it

baseclass
^
|
extendedclass
^
|
extendedextendedclass

and "upcasting" is climbing along the arrow?


So it seems that "downcasting" is not possible (without many steps to climb - which you, yasha, could surely achieve, but "average joe" would not) in BlitzMax (I also do not have a really useful example for "joe").


bye
Ron


H&K(Posted 2014) [#7]
Because its a root diagram NOT a tree diagram.


Derron(Posted 2014) [#8]
Hmm so I really have to get rid of my "image" of inheritance. I just used that "tree-approach" ("at the end it all comes down to ...").

Maybe I also thought of it because it is called "Base" (eg. TBaseClass) and I translated "Base" with "Ground" or "Basic" (in German "Grundlage", with "Ground" translateable to "Grund"). I think it will get really hard to memorize this now.. if I ever will.


bye
Ron


Yasha(Posted 2014) [#9]
I assume the etymology is related to the notions of subtyping vs. supertyping. The more specific you get, the more you close in on a sub-set of types, so you go down. Maybe.

Anyway, downcasting is easy in BlitzMax - given the above (#3) example, if you have an object of type Entity and want an object of type Figure:

Local f:Figure = Figure(e)


If e was actually an Enemy or Player, f will now be null. This is the same thing you do when getting an object out of a TList.

Casting between object types is written in just the same way as converting between e.g. Int and String. (The compiler will not let you insert a cast between two types that aren't connected by any subtyping relationship, e.g. it will complain if you try to cast a Figure to a Player, because this is always wrong.)


Derron(Posted 2014) [#10]
Hmpf... somehow I thought of something different when thinking about "examples"...

Of course you are right -- again. And I use that "downcasting" very often - eg. Passing the "baseclass" as params, and then checking if it was an extension.

So in my game things you can send over your TV channel are "TBroadcastMaterial", but it has special variations: "TNewsShow extends TBroadcastMaterial", "TProgramme extends TBroadcastMaterial".

So instead of storing the "type" in a property, I can check if the given broadcastMaterial is of type "TNewsShow" or not. I also use it for different incarnations of BaseEvent, PlayerEvent ...


Means: Downcasting is used often and not that hard. But what is with upcasting? It is implicitely included - as objects "extend" from the upper one ... So when "upcasting" it still uses the overriden methods instead of the one I want to use.




But I thought, when "upcasting" this also means using the methods of the type upcasted to.
I know you can use "super." to access parental type's methods/fields - but what if I want to climb up the ladder even more (eg. "enemy" wants to run the "method incarnation" of "entity" - which is 2 tiers away). I do not have a useful idea when to use this ... but maybe an extended element only wants to use a custom behaviour in special cases and in all other ones the behaviour of a specific ancestor)


bye
Ron