Cast vs Virtual Method vs TypeId?
Jonathan Marler via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Wed Jun 29 17:25:53 PDT 2016
I'd like to hear peoples thoughts on the various solutions for
the following problem. Say you have some hierarchy of classes
like:
class GameObject {
// ...
}
class Entity : GameObject {
// ...
}
class Player : Entity {
// ...
}
class Enemy : Entity {
// ...
}
// ...
Assume you have a function that accepts a GameObject but does
something special if that GameObject happens to be an instance of
the Player class. How would you go about determining this? (Note:
assume you need to make the distinction at runtime, so you can't
use a static if with an 'is' expression inside a template.)
I'd like to hear what people think in 2 cases
1) Only need to know if it's an instance of the Player class.
2) Need to know if it's an instance of the Player class AND
need an instance of the Player class.
The potential solutions I thought of were:
1) typeid (Only handles case 1)
if(typeid(obj) == typeid(Player) {
// treat as player object
}
If you don't need an instance of the Player class, maybe this one
is good? I don't know in terms of efficiency if this is better,
or casting is better. Maybe cast uses the typeid under the hood
to determine if the cast can be performed?
2) Custom Type Enum (Only handles case 1)
enum GameObjectType {
gameObject, player, ...
}
class GameObject {
GameObjectType type;
}
if(obj.type == GameObjectType.player) {
// treat it as a player object
// Note: if you need to use Player class specific fields
// then you'll need to use the cast or virtual function
// design which kinda defeats the purpose of this design
in the
// case where it is actually a Player object.
}
This method may be similar to the typeid method, not sure since I
don't know how typeid works under the hood. If it's similar then
this would just be a waste of memory and should not be used in
favor of the typeid method.
3) Cast (Handles case 1 and 2)
auto player = cast(Player)obj;
if(player) {
// treat it as a player object
}
I don't know how cast works under the hood so it's hard to
compare it to other methods. Any information on how cast works
under the hood would be great.
4) Virtual Method (Handles case 1 and 2)
class GameObject {
Player asPlayer() { return null; }
}
class Player {
override Player asPlayer() { return this; }
}
auto player = obj.asPlayer;
if(player) {
// treat it as a player object
} else {
// treat it as any other game object
}
This solution handles the same cases as regular casting, but I
can't compare them since I don't know how casting works under the
hood. One thing to consider is that this method scales linearly
since you need to add a new virtual method for every type you
want to support, so the vtable gets larger as you add more types.
Any other solutions? Thoughts? Thanks in advance for the
feedback.
More information about the Digitalmars-d-learn
mailing list