Generics 如何在泛型函数中转换为动态类型?

Generics 如何在泛型函数中转换为动态类型?,generics,casting,haxe,Generics,Casting,Haxe,我有一个基本的原型类: class CItemProto { public var id:Int; public var count:Int; ... } 以及一些不同类型的扩展: class CItemThing extends CItemProto { ... } class CItemResource extends CItemProto { ... } class CItemRecipe extends CItemProto { ... } ……等等。每

我有一个基本的原型类:

class CItemProto {

    public var id:Int;

    public var count:Int;

    ...
}
以及一些不同类型的扩展:

class CItemThing extends CItemProto { ... }
class CItemResource extends CItemProto { ... }
class CItemRecipe extends CItemProto { ... }
……等等。每个item实例都有唯一的id,因此我可以使用简单的IntMap访问将我的所有资料存储在一个inventory类中:

class CInventory {

    var mMap:IntMap<CItemProto>;

    public function new() {
        mMap = new IntMap();
    }

    public inline function set(item:CItemProto) { mMap.set(item.id, item); }

    public function get<T:CItemProto>(id:Int):T {
        var item = mMap.get(aId);
        if (Std.is(item, Class<T>)) // it doesn't work saying Unexpected )
            return cast item;
        return null;
    }

}
但它不起作用。如果我请求错误的类型,简单不安全强制转换将失败,安全强制转换要求动态类型,而不是通用的T替换。我应该怎么做才能按类型筛选请求的项目?当然,我可以将type作为第二个参数传递,但它看起来笨重且过度


更新我找到了主题,所以我的问题毫无意义。我将传递所需的类型作为第二个参数。

我做了一个非常糟糕的解决方法:

typedef Constructible = {
    function new():Void;
}

@:generic
public function get<T:(CItemProto,Constructible)>(id:Int):Null<T> {
    var typed = new T();
    var item:CItemProto = mMap.get(id);
    if (Std.is(item, Type.getClass(typed)))
        return cast item;
    return null;
}

但是你不应该这样做。

我做了一个非常难看的解决办法:

typedef Constructible = {
    function new():Void;
}

@:generic
public function get<T:(CItemProto,Constructible)>(id:Int):Null<T> {
    var typed = new T();
    var item:CItemProto = mMap.get(id);
    if (Std.is(item, Type.getClass(typed)))
        return cast item;
    return null;
}

但是你不应该这样做。

我会用这样的方法:

public function safeGetAs<T:CItemProto>(id:Int, c:Class<T>):T {
    var v = mMap.get(id);
    if (Std.is(v, c)) return cast v;
    return null;
}

演示:

我会使用如下内容:

public function safeGetAs<T:CItemProto>(id:Int, c:Class<T>):T {
    var v = mMap.get(id);
    if (Std.is(v, c)) return cast v;
    return null;
}

演示:

谢谢,我也做了同样的解决方案。现在我明白了将类作为预期数据类型传递并不是缺点。您可以使用
return Std.instance(v,c)
替换
if..return cast…return null
谢谢,我也提出了同样的解决方案。现在我明白了将类作为预期数据类型传递并不是缺点。您可以使用
return Std.instance(v,c)
替换
if..return cast…return null
创建一个实例来获取它的类?为什么要发布一个以“但你不应该这样做”结尾的答案呢?创建一个实例来获取它的类?为什么要贴一个以“但你不应该这样做”结尾的答案呢。
inventory.set(new CItemThing(1));
inventory.set(new CItemResource(2));

var a = inventory.safeGetAs(1, CItemThing);
trace(a); // returns instance
$type(a); // expected: CItemThing. is: CItemThing. 

var b = inventory.safeGetAs(2, CItemThing);
trace(b); // returns null
$type(b); // expected: CItemThing. is: CItemResource.