- Joined
- Jul 17, 2017
- Messages
- 76
I just found out that I can do a thing with classes that I didn't realize was possible & wanted to share it. I've never really played with the "Class Thing<T>" structure (I don't know the name of it) so didn't know exactly what I could do with the given T.
Well, apparently, you can make new instances of that T and then cast that to other object types, including abstract ones!
So I can now make generators for any of the classes in my game, and load and cache them all the same way. It just blows my mind that the same exact same method (the manager's Get) can end up returning a different object type.
I guess that lists and stuff have been doing this all along (e.g. a Stack<Limb>'s Pop() returns a Limb) but I never realized that this same power could be mine to command.
Does anybody else use the <T> pattern much? Are there other tips or pitfalls I should watch out for?
Well, apparently, you can make new instances of that T and then cast that to other object types, including abstract ones!
Cerberus:
Class Generator Abstract
Method name$() Abstract Property
Method Init:Void(file$) Abstract
End
Class GeneratorManager<GeneratorType>
'A map of created generators keyed by their file name.
Field loadedGenerators:= New StringMap< Generator >
'This is where the magic is. Being able to create a NEW OBJECT of an
'ARBITRARY TYPE and then cast it to an ABSTRACT CLASS (which I can
'then call methods on??) seems like dark magic to me.
Method Create:Generator(file$)
local g:Generator = Generator(New GeneratorType)
g.Init(file)
loadedGenerators.Add(g.name, g)
return g
End
'Gets a loaded generator ~OR~ creates a new one if it doesn't exist
Method Get:GeneratorType(file$)
local g:Generator = loadedGenerators.Get(file)
if g = Null then g = Create(file)
Return GeneratorType(g)
End
End
So I can now make generators for any of the classes in my game, and load and cache them all the same way. It just blows my mind that the same exact same method (the manager's Get) can end up returning a different object type.
Cerberus:
Class LimbGenerator Extends Generator
Field script:LimbScript
Method name$() Property
return script.name
End
Method Init:Void(file$)
script = New LimbScript(file)
End
Method MakeLimb:Limb()
Local limb:= New Limb
script.SetupLimb(limb)
return limb
End
End
' -- make some limbs -- '
local limbGeneratorManager:= New GeneratorManager<LimbGenerator>
local armGenerator:LimbGenerator = limbGeneratorManager.Get("arm.mc")
local arm:Limb = armGenerator.MakeLimb()
local legGenerator:LimbGenerator = limbGeneratorManager.Get("leg.mc")
local leg:Limb = legGenerator.MakeLimb()
' -- make some neurons -- '
local neuronGeneratorManager:= New GeneratorManager<NeuronGenerator>
local motorGenerator:NeuronGenerator = neuronGeneratorManager.Get("motor.mc")
local motor:Neuron = motorGenerator.MakeNeuron()
local reflexGenerator:NeuronGenerator = neuronGeneratorManager.Get("reflex.mc")
local reflex:Neuron = reflexGenerator.MakeNeuron()
I guess that lists and stuff have been doing this all along (e.g. a Stack<Limb>'s Pop() returns a Limb) but I never realized that this same power could be mine to command.
Does anybody else use the <T> pattern much? Are there other tips or pitfalls I should watch out for?