在Haxe中使用Class <t>作为Map键

时间:2019-02-08 21:12:49

标签: inversion-of-control haxe

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

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>();

}

... ala,它甚至没有编译。 可能我必须使用合格的类名作为键而不是类/接口引用?但是我想保持整洁的get函数设计,该函数将类型作为参数并返回仅采用类型的对象,而无需进行其他类型转换。

是否有可能或者应该更改此问题的方法?

1 个答案:

答案 0 :(得分:6)

使用Class<T>作为Map键的问题经常出现,here是一个相关的讨论。 Map<Class<T>, T>的幼稚方法无法通过以下方式进行编译:

  

抽象haxe.ds.Map没有@:to函数接受haxe.IMap ,Main.T>`

有几种解决此问题的方法:

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

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

    为方便起见,您可能想要一个包装为您完成此操作,例如this ClassMap implementation


  • 一个更简单的解决方案是通过使用空结构类型({})作为键类型来简单地“欺骗” 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 {} {}
    

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

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