【发布时间】:2014-01-25 14:29:22
【问题描述】:
Java 和 Javascript 都允许以不同的方式执行静态代码。 Java 允许您在类的主体中拥有静态代码,而 JS 允许您在类定义之外执行静态代码。例子:
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(基本上是类外的任何 JS 代码):
var myint = 5;
callSomeMethod();
$(document).ready(function () {
$("#hiddenelement").hide();
});
但是,Dart 似乎支持这两种方式中的任何一种。支持声明全局变量和方法,但不支持像 JS 中那样调用方法和执行代码。这只能在main() 方法中完成。另外,类中的静态代码也是不允许的。
我知道 Dart 有其他方法可以像我的第一个示例一样静态填充 Map,但是我可以想到另一种情况需要这样做。
让我们考虑以下CarRegistry 实现,它允许您将汽车模型的字符串映射到相应类的实例。 F.e.当您从 JSON 数据中获取汽车模型时:
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 {
}
为了能够调用CarRegistry.createInstance("teslamodelx");,必须首先注册该类。在 Java 中,这可以通过在每个 Car 类中添加以下行来完成:static { CarRegistry.registerFactory("teslamodelx" , () => new TeslaModelX()); }。您不希望将所有汽车硬编码到注册表中,因为它会失去它作为注册表的功能,并且会增加耦合度。您希望能够通过仅添加一个新文件来添加新车。在 JS 中,您可以在类构造之外调用 CarRegistry.registerFactory("teslamodelx" , () => new TeslaModelX()); 行。
如何在 Dart 中完成类似的事情?
即使您允许编辑多个文件以添加新车,如果您编写的库没有main() 方法也是不可能的。唯一的选择是在第一次调用 Registry.createInstance() 方法时填充地图,但它不再是注册表,而是包含硬编码汽车列表的类。
编辑:对我在此处所做的最后声明的一个小补充:仅当注册表驻留在我自己的库中时,才可以选择在 createInstance() 方法中填充这种注册表。如果,f.e.我想将自己的类注册到由我导入的不同库提供的注册表中,这不再是一个选项。
【问题讨论】: