Singletons
Standard Singletons
- Declaring a class a singleton makes a "global" object that can be accessed via the class name. An example:
singleton class World PROPERTIES entities() : Entity[] ... endClass ... World.entities.add( SomeMonster() ) World.fn(true) - A World object is created at load time and assigned to the global reference World.
- You can still create other World objects: "local World w = World(...)".
- You can reassign the singleton reference as desired: "World = World(...)", "World = null".
- A singleton's default init() method is called if it exists.
- Co-dependent singletons will likely experience order of initialization issues. In that case you can use deferred singletons instead.
- Singletons can be specified as implict context for any class. To make class World an implicit singleton for class entity so that within an Entity a reference to "entities" becomes "World.entities":
class Entity SINGLETONS World [, OtherSingleton, ...] ... endClass - You may get the error message "Singleton calls cannot have a context expression". What's happening is you've said something like this: "controller.get_hero.entities.add( Bullet() )". If "entities" is part of "World", then the call actually becomes "World.entities.add( Bullet() )". The compiler is left wondering what to do with the "controller.get_hero" part of the call. If it can determine that that context has no side effects (and the logic for this is currently very simplistic) than it just discards the context. Otherwise it throws an error.
- Slag doesn't actually have class properties or class methods underneath. Anything declared as a class property or a class method for some class Entity is placed into an automatically-generated singleton called EntityManager and EntityManager becomes an implicit singleton of Entity.
Deferred Singletons
- A deferred singleton is a singleton that is not instantiated until it is first accessed. This access may be as simple as writing the name of the singleton. An example:
class Main method init: println( "This prints first" ) DeferredDemo endClass deferred singleton class DeferredDemo method init: println( "This prints second" ) endClass - The compiler converts a deferred singleton into a managed singleton that incorporates the Automanaged aspect.
Managed Singletons
While standard singletons have a global reference that is directly accessed, managed singletons rely on singleton manager class to code that retrieves or sets the singleton value.
# This code:
managed singleton class World
...
endClass
World.time = 1630
World = load_world
# is translated by the compiler into this code:
class World
SINGLETONS
WorldManager
...
endClass
WorldManager.get().time = 1630
WorldManager.set( load_world )
It is up to you to define "WorldManager" - in most cases just use a deferred singleton which will provide a standard implementation.
Caveats
- Deferred singletons aren't stored in their slot until their initializer finishes running. This can cause dependency problems - for example, say World and Hero are both deferred singletons. If World accesses Hero in its initializer and Hero accesses World in its initializer, that last access will get a Null Reference Error because World hasn't finished initializing yet.
- Login to post comments
