2016-06-09 56 views
1

我有一個基本的原型類:如何在通用函數中轉換爲動態類型?

class CItemProto { 

    public var id:Int; 

    public var count:Int; 

    ... 
} 

和別樣的一些擴展:

class CItemThing extends CItemProto { ... } 
class CItemResource extends CItemProto { ... } 
class CItemRecipe extends CItemProto { ... } 

...等等。項目的每個實例都具有唯一的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()訪問一些項目編號以及此項目類型如果我在選擇類型時出錯,方法應該返回null值。例如:

// should return instance of CItemThing if it exists or null in the other way 
var thing:CItemThing = inventory.get(123); 

但它不起作用。如果我要求錯誤類型,安全投出要求,簡單不安全的投射失敗動態類型代替通用T替代。我應該怎麼做才能根據其類型過濾請求的項目?因爲我可以通過類型作爲第二個參數,但它看起來很笨重和過度。

UPDATE我找到了主題How to look for a class type in an array using generics所以我的問題沒有意義。我將通過所需的類型作爲第二個參數。

回答

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. 

演示:http://try.haxe.org/#65792

+0

謝謝,我已經做出了相同的解決方案。現在我看到,將類作爲預期數據的類型傳遞並不是什麼缺點。 – meps

+0

你可以使用'return Std.instance(v,c)'來代替'if..return cast ... return null' – KevinResoL

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

但你不應該做這樣的。

+1

創建一個實例來獲得它的類?爲什麼甚至發佈一個以'但你不應該這樣做'爲結束的答案'。 –