Java和Javascript都允许以不同的方式执行静态代码。 Java允许您在类的主体中拥有静态代码,而JS允许您在类定义之外执行静态代码。例子:
爪哇:
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。我想将自己的类注册到我导入的不同库提供的注册表中,这不再是一个选项。
答案 0 :(得分:3)
为什么所有关于静电的大惊小怪?
您可以创建一个getter来检查初始化是否已经完成(_factoryMethods != null
),如果不这样做并返回映射。
据我所知,这完全取决于代码执行的时间。
我上面展示的方法是延迟初始化
我认为这通常是我猜的首选方式
如果要在加载库时进行初始化
我不知道从init()
调用库的main()
方法并添加此库init()
方法的初始化代码的另一种方法。
答案 1 :(得分:1)
我在尝试驾驶类似主题的图书馆时遇到了同样的问题。
我的初步尝试探索了使用dart:mirrors
迭代库中的类并确定它们是否被这样的注释标记(使用您自己的代码作为示例的一部分):
@car('telsamodelx')
class TelsaModelX extends Car {
}
如果是这样,他们会自动填入注册表。但是,表现并不好,我不确定它是如何扩展的。
我最终采取了更加繁琐的方法:
// Inside of CarRegistry.dart
class CarRegister {
static bool _registeredAll = false;
static Car create() {
if (!_registeredAll) { _registerAll()); }
/* ... */
}
}
// Inside of the same library, telsa_model_x.dart
class TelsaModelX extends Car {}
// Inside of the same library, global namespace:
// This method registers all "default" vehicles in the vehicle registery.
_registerAll() {
register('telsamodelx', () => new TelsaModelX());
}
// Inside of the same library, global namespace:
register(carName, carFxn) { /* ... */ }
在图书馆之外,消费者不得不在某个地方拨打register();
来注册他们的车辆。
这是不必要的重复,并且遗憾的是,以一种难以跟踪的方式将注册与课程分开,但使用dart:mirrors.
YMMV,但随着可注册项目数量的增加,我开始再次关注dart:mirrors
方法。