Type
In many programming languages, you can simply provide a Type and have the language generate a new instance of that Type using reflection. However, Dart does not include the ability to instantiate types during runtime to keep the generated programs lean and efficient. The Type module in the Flood toolkit addresses this limitation by introducing RuntimeTypes, which allow you to define and instantiate types dynamically.
Context
To start using the Type Module, you first need to create a TypeContext. This context stores information about every Type you want to instantiate, including the types it extends and how to instantiate the type (if it's not abstract).
Here's an example of setting up a TypeContext:
final context = TypeContext();
context.registerAbstract<MyAbstractClass>(name: 'MyAbstractClass');
context.register<MyConcreteClass>(MyConcreteClass.new, name: 'MyConcreteClass', parents: [MyAbstractClass]);Note that you need to specify a name for each of the Types. This is crucial when Dart is compiled to web and minified, as the names of the Types can be jumbled up. Specifying a name ensures that you can create an instance of a Type based on its name, like this:
context.getByName('MyConcreteClass').createInstance();For concrete classes, you also need to specify how to generate new instances. In the example above, a new instance of MyConcreteClass is created using MyConcreteClass.new (Dart syntax sugar for () => MyConcreteClass()).
RuntimeTypes
The Type module exports the RuntimeType class, which contains information about a single Type, such as how to instantiate it, its parents or children, and whether it is abstract.
Once you register a Type using a TypeContext, you can retrieve its RuntimeType using one of the following methods:
myConcreteRuntimeType = context.getRuntimeType<MyConcreteClass>();
myConcreteRuntimeType = context.getRuntimeTypeRuntime(MyConcreteClass);
myConcreteRuntimeType = context.getByName('MyConcreteClass');Here's how you can access information from a RuntimeType:
myConcreteRuntimeType.getAncestors() // [RuntimeType<MyAbstractClass>]
myConcreteRuntimeType.getChildren() // []
myConcreteRuntimeType.getDescendants() // []
myConcreteRuntimeType.isA(myAbstractRuntimeType) // trueGenerating Instances
There are two ways to generate an instance of a RuntimeType:
- Using the
createInstance()method on theRuntimeTypeitself:
myConcreteRuntimeType.createInstance();- Using the
construct()method on theTypeContext:
typeContext.construct(MyConcreteClass);Note that attempting to create an instance of an abstract RuntimeType will throw an error.
By leveraging the Type module in the Flood toolkit, you can effectively manage and instantiate runtime types in your Dart and Flutter applications. This enables dynamic type creation while maintaining the efficiency and performance benefits of Dart's design philosophy.
Use with Pond
The Type Module is automatically registered when you use the FloodCoreComponent. You can extract the TypeContext from the CorePondContext like so:
final typeContext = corePondContext.locate<TypeCoreComponent>();