我有一个基本的原型类:
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访问权限的库存类中:
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;
}
}
我的观点是将 get()访问器与某个项ID和此项类型一起使用,如果我在类型选择中出错,则方法应返回 null 值。例如:
// should return instance of CItemThing if it exists or null in the other way
var thing:CItemThing = inventory.get(123);
但它不起作用。如果我请求错误类型,安全演员要求动态类型而不是通用 T 替换,则简单的不安全强制转换会失败。我应该怎么做才能按类型过滤所请求的项目?因为我可以传递类型作为第二个参数,但它看起来笨重而且过分。
更新我找到了主题How to look for a class type in an array using generics,所以我的问题毫无意义。我会将所需的类型作为第二个参数传递。
答案 0 :(得分:1)
我会用这样的东西:
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;
}
然后你必须明确地输入你想要的东西,因为这不是可以解决编译时间的东西。打字也更有意义:
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.
答案 1 :(得分:-1)
我做了一个非常丑陋的解决方法:
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;
}
现在我可以申请任何类型的项目,如:
var thing:CItemThing = inventory.get(111);
var resource:CItemResource = inventory.get(222);
但你不应该这样做。