在 Haxe 中使用 Class<T> 作为映射键

Using Class<T> as a Map key in Haxe

我想使用它们的 classes 或接口作为键将模型实例存储在一个公共提供程序中,然后通过 class 引用弹出它们。我写了一些代码:

class Provider {

    public function new() { }

    public function set<T:Any>(instance:T, ?type:Class<T>) {
        if (type == null)
            type = Type.getClass(instance);
        if (type != null && instance != null)
            map.set(type, instance);
    }

    public function get<T:Any>(type:Class<T>):Null<T> {
        return cast map.get(type);
    }

    var map = new Map<Class<Any>, Any>();

}

...唉,连编译都不行。 可能我必须使用合格的 class 名称作为键而不是 class/interface 引用?但我想保持整洁的 get 函数设计,将类型作为参数,returns 对象只是采用的类型,没有额外的类型转换。

是否有可能或者我应该改变我解决这个问题的方法?

使用Class<T> as a Map key come up every so often, here的问题是一个相关的讨论。 Map<Class<T>, T> 的天真方法无法用这样的东西编译:

Abstract haxe.ds.Map has no @:to function that accepts haxe.IMap<Class<Main.T>, Main.T>`

有几种不同的方法可以解决这个问题:

  • 可以使用 Type 反射获取 class 实例的完全限定名称,然后将其用作 Map<String, T> 中的键:

    var map = new Map<String, Any>();
    var name = Type.getClassName(Main);
    map[name] = value;
    

    为方便起见,您可能希望有一个包装器可以为您完成此操作,例如 this ClassMap implementation.


  • 一个更简单的解决方案是通过使用空结构类型 ({}) 作为键类型来简单地 "trick" Haxe 编译它。这导致 ObjectMap 被选为底层地图实现。

    var map = new Map<{}, Any>();
    map[Main] = value;
    

    但是,这允许您将非 Class<T> 类型的东西用作键,例如:

    map[{foo: "bar"}] = value;
    

  • 可以通过使用 this ClassKey abstract:

    来解决之前方法的类型安全问题
    @:coreType abstract ClassKey from Class<Dynamic> to {} {}
    

    由于 to {} implicit cast,这仍然使用 ObjectMap 作为基础地图实现。但是,现在使用结构作为键在编译时失败:

    var map = new Map<ClassKey, Any>();
    map[{foo: "bar"}] = value; // No @:arrayAccess function accepts arguments [...]