Both Java and Javascript allow for a different way of executing static code. Java allows you to have static code in the body of a class while JS allows you to execute static code outside class definitions. Examples:
Java:
public class MyClass {
private static Map<String,String> someMap = new HashMap<String,String();
static {
someMap.put("key1","value");
someMap.put("key2","value");
SomeOtherClass.someOtherStaticMethod();
System.out.println(someMap);
}
}
JS (basically any JS code outside a class):
var myint = 5;
callSomeMethod();
$(document).ready(function () {
$("#hiddenelement").hide();
});
However, it seems like Dart supports either of both ways. Declaring global variables and methods is supported, but calling methods and executing code like in JS is not. This can only be done in a main()
method. Also, static code inside a class is not allowed either.
I know Dart has other ways to statically fill a Map like my first example, but there is another case that I can think of for which this is required.
Let's consider the following CarRegistry
implementation that allows you to map strings of the car model to an instance of the corresponding class. F.e. when you get the car models from JSON data:
class CarRegistry {
static Map<String, Function> _factoryMethods = new HashMap<String, Function>();
static void registerFactory(String key, Car factory()) {
_factoryMethods[key] = factory;
}
static Car createInstance(String key) {
Function factory = _factoryMethods[key];
if(factory != null) {
return factory();
}
throw new Exception("Key not found: $key");
}
}
class TeslaModelS extends Car {
}
class TeslaModelX extends Car {
}
In order to be able to call CarRegistry.createInstance("teslamodelx");
, the class must first be registered. In Java this could be done by adding the following line to each Car
class: static { CarRegistry.registerFactory("teslamodelx" , () => new TeslaModelX()); }
. What you don't want is to hard-code all cars into the registry, because it will lose it's function as a registry, and it increases coupling. You want to be able to add a new car by only adding one new file. In JS you could call the CarRegistry.registerFactory("teslamodelx" , () => new TeslaModelX());
line outside the class construct.
How could a similar thing be done in Dart?
Even if you would allow to edit multiple files to add a new car, it would not be possible if you are writing a library without a main()
method. The only option then is to fill the map on the first call of the Registry.createInstance()
method, but it's no longer a registry then, just a class containing a hard-coded list of cars.
EDIT: A small addition to the last statement I made here: filling this kind of registry in the createInstance()
method is only an option if the registry resided in my own library. If, f.e. I want to register my own classes to a registry provided by a different library that I imported, that's no longer an option.