So, if I understand it right, when you have to update an object of a certain
type, you generally have to do the same thing to all objects of that type.
Thus, having the object store a pointer to its update function isn't very
helpful, since you can just keep a table of all such objects that could be
updated in that way. Polymorphism generally means that you have oversimplified
your system, and made over-broad general statements, that could be better
specified.
In the entity example for instance, if "fighters" and "flyers" both need to
update the same way, they can share a common base update function, with no
polymorphism. If "fighters" need to update in a different way from "flyers"
then it's probably a bad idea to call both those two different operations
"update".
type Fighter = ...
proc drive(f: var Fighter) = ...
type Flyer = ...
proc fly(f: var Flyer) = ...
var
flyers: seq[Flyer]
fighers: seq[Fighter]
for f in flyers: f.drive
for f in fighters: f.fly
If both have the same "PhysicsComponent" base, then you'd just say...
var
entities: seq[PhysicsComponent]
proc createFlyer(...) =
...
entities.add(self.phys)
proc createFighter(...) =
...
entities.add(self.phys)
...
for fighter in fighters:
fighter.drive()
for flyer in flyers:
flyer.fly()
for entity in entities:
entity.updatePhysics()
Each fighter and flyer has to be accessed twice this way, once as either
drive/fly, and once as their general physical properties, but that's faster
than accessing each entity once, and then having a pointer/enum to decide
whether to update it in the "drive" sense, or the "fly" sense. You also need to
store two pointers for every entity, one for "entities" and one for either
"fighters" or "flyers", but with polymorphism you need to store a pointer to
the custom update function anyway.
There would be potential space saved if you used enum style polymorphism,
like...
for entity in entities:
case(entity.type)
of FIGHTER:
drive(entity)
of FLYER:
fly(entity)
else:
error("has to be a fighter or a flyer");
entity.updatePhysics()
Your "type" variable could be a single byte, or even a bit within some kind of
"entity.state" bitfield, whereas with separate lists for fighters and flyers,
at best they have to store a 2 byte integer to index a table of entities, and
even then that limits the amount of entities you can have to 0xFFFF.
That's the only reason I could think to use polymorphism, is if you're so
severely memory constrained that 4/8 bytes more per entity is a deal breaker.