Использование класса <T>в качестве ключа карты в Haxe - PullRequest
0 голосов
/ 09 февраля 2019

Я хотел бы хранить экземпляры моделей в общем поставщике, используя их классы или интерфейсы в качестве ключей, а затем отображать их по ссылкам на классы.Я написал некоторый код:

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

}

... увы, он даже не компилируется.Возможно, я должен использовать квалифицированное имя класса в качестве ключа, а не ссылку на класс / интерфейс?Но я хотел бы сохранить аккуратный дизайн функции get, который принимает тип в качестве аргумента и возвращает объект только взятого типа, без дополнительного приведения типов.

Возможно ли это или я должен изменить свой подход к этой проблеме?

1 Ответ

0 голосов
/ 09 февраля 2019

Проблема использования Class<T> в качестве клавиши Map возникает очень часто, здесь - это связанное обсуждение.Наивный подход Map<Class<T>, T> не компилируется с чем-то вроде этого:

Аннотация haxe.ds.Map не имеет функции @: для функции, которая принимает haxe.IMap, Main.T> `

Существует несколько различных подходов к этой проблеме:

  • Можно использовать Type отражение для полученияполное имя экземпляра класса, а затем используйте его в качестве ключа в Map<String, T>:

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

    . Для удобства вам, вероятно, понадобится оболочка, которая сделает это за вас, например: это ClassMap реализация .


  • Более простое решение состоит в том, чтобы просто "обмануть" 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 в качестве базовой реализации карты из-за неявного приведения to {} .Однако использование структуры в качестве ключа теперь не выполняется во время компиляции:

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