@:通用仅适用于某些类型参数

时间:2019-12-11 15:59:15

标签: haxe

如果我想创建带有2个类型参数的类,并且想要为使用的每个第一个类型参数进行专门的实现,但是我不希望为第二个类型参数使用它。

例如,我想要自己的地图

copy

这将为所使用的K和V的每种组合生成实现。但是我只想为K使用不同的实现。

我尝试使用所需的类型参数在@:generic @:remove class MyMap { public var map: Map<K, V> = new Map(); public function new() {} } 类上制作abstract,或扩展此类。但这是行不通的。 haxe编译器通过两种方式都会生成MyMapBase类的创建,而根本不会生成该类。

@:generic

2 个答案:

答案 0 :(得分:0)

这是我的解决方案。我使用了@:multiType抽象。这个功能在haxe中没有得到很好的记录,但是可以看看Map的实现。

@:generic @:remove
class MyMapImpl<K> implements IMyMap<K, Dynamic> {
    public var map: Map<K, Dynamic> = new Map();
    public function new() {}
}

interface IMyMap<K, V> {
    public var map: Map<K, V>;
}

@:multiType(K)
abstract MyMap<K, V>(IMyMap<K, V>) {

    public function new();

    public var map(get, never): Map<K, V>;

    inline function get_map(): Map<K, V> {
        return this.map;
    }

    @:to static inline function toStringMap<K:String, V>(t:IMyMap<K, V>):MyMapImpl<String> {
        return cast new MyMapImpl<String>();
    }

    @:to static inline function toIntMap<K:Int, V>(t:IMyMap<K, V>):MyMapImpl<Int> {
        return cast new MyMapImpl<Int>();
    }
}


class Main {
    static function main() {
        var m = new MyMap<String, Int>();
        trace(Type.getClassName(Type.getClass(m))); //MyMapImpl_String
        trace(Type.getClassName(Type.getClass(m.map))); //haxe.ds.StringMap

        var m = new MyMap<String, String>();
        trace(Type.getClassName(Type.getClass(m))); //MyMapImpl_String
        trace(Type.getClassName(Type.getClass(m.map))); //haxe.ds.StringMap

        var m = new MyMap<Int, Int>(); 
        trace(Type.getClassName(Type.getClass(m))); //MyMapImpl_Int
        trace(Type.getClassName(Type.getClass(m.map))); //haxe.ds.IntMap
    }
}

答案 1 :(得分:0)

您根本不需要自己的课程。而且,由于您的值是动态存储的,因此每个键类型只需要一个映射实例。如果不希望这样做,则可以将其更改回每个值的实例,但是为什么要使用动态值?无论如何,这是一个适用于所有目标的地图版本。

@:multiType
abstract MyMap<K, V>(Map<K, Dynamic>) {

    public function new();

    public inline function set(k:K, v:V) this.set(k, v);
    public inline function get(k:K) return this.get(k);

    public static var string_map = new Map<String, Dynamic>();
    @:to static inline function toStringMap<K:String>(t:Map<K, Dynamic>) {
        return string_map;
    }

    public static var int_map = new Map<Int, Dynamic>();
    @:to static inline function toIntMap<K:Int>(t:Map<K, Dynamic>) {
        return int_map;
    }

    public static var object_map = new Map<{}, Dynamic>();
    @:to static inline function toObjectMap<K:{}>(t:Map<K, Dynamic>) {
        return object_map;
    }
}
    var i = new MyMap<String, Int>();
    i.set("zero", 0);
    trace(Type.getClassName(Type.getClass(i))); //haxe.ds.StringMap
    trace(i); // {zero => 0}
    var s = new MyMap<String, String>();
    s.set("one", "1");
    trace(Type.getClassName(Type.getClass(s))); //haxe.ds.StringMap
    trace(s); // {zero => 0, one => 1}
    // var v:Int = i.get("one") will fail on Java and HL
    // we let v to infer as Null<Dynamic> instead
    var v = i.get("one");
    trace(v);