2017-02-11 16 views
3

Я ищу безопасный способ для вилки в зависимости от типа объекта. Я не узнал, как проверить, принадлежит ли объект определенному родовому типу.Как проверить, что объект является экземпляром generic в Haxe

class Test { 
    static function main() { 
     var aa = new AA<Int>(); 
     //ERROR: Cast type parameters must be Dynamic 
     //var a:A<Int> = cast(aa, A<Int>); 

     //ERROR: Unexpected) 
     //var a:A<Int> = Std.instance(aa, A<Int>); 

     //OK, but throw run-time exception with flash target. 
     var a:A<Int> = cast aa; 
     a.printName(); 

     //Run-time exception 
     a = cast "String is obviously wrong type"; 
    } 
} 

class A<T> { 
    public function new() { } 
    public function printName() { 
     trace("Generic name: A"); 
    } 
} 

class AA<T> extends A<T> { 
    public function new() { super(); } 
    override public function printName() { 
     trace("Generic name AA"); 
    } 
} 

Есть ли законный способ проверить, принадлежит ли объект родовому типу?

+0

Я не могу воспроизвести это исключение, которое вы используете во Flash. Кроме того, в вашем фрагменте кода отсутствует объявление типа для 'B'. – Gama11

+0

Вы можете проверить это http://try.haxe.org/#C6a93 с помощью SWF-мишени и отладочной flash-плеера. – kolonitsky

ответ

4

Как правило, нет большого способа сделать это, потому что информация больше недоступна во время выполнения. Вы можете использовать один и тот же обходной путь, который often suggested for Java, который хранящий общий тип в своем классе:

class Main { 
    static function main() { 
     var a = new A<Int>(Int); 

     trace(a.typeParamIs(Int)); // true 
     trace(a.typeParamIs(Bool)); // false 
    } 
} 

class A<T> { 
    var type:Any; 

    public function new (type:Any) { 
     this.type = type; 
    } 

    public function typeParamIs(type:Any):Bool { 
     return this.type == type; 
    } 
} 

В качестве альтернативы, вы можете использовать Type.typeOf() как это, если A имеет поле типа T:

class Main { 
    static function main() { 
     checkType(new A<Int>(5)); // Int 
     checkType(new A<Bool>(true)); // Bool 
     checkType(new A<B>(new B())); // B 
     checkType(new A<B>(null)); // unhandled type TNull 
    } 

    static function checkType<T>(a:A<T>) { 
     trace(switch (Type.typeof(a.value)) { 
      case TInt: "Int"; 
      case TBool: "Bool"; 
      case TClass(cls) if (cls == B): "B"; 
      case other: throw "unhandled type " + other; 
     }); 
    } 
} 

class A<T> { 
    public var value:T; 
    public function new (value:T) { 
     this.value = value; 
    } 
} 

class B { 
    public function new() {} 
} 

Как вы можете видеть, хотя это обычно работает, это может привести к неожиданному поведению в некоторых случаях - например, когда value - null. Также имейте в виду документы от Type.typeOf():

Может варьироваться в зависимости от платформы. Предположения относительно этого должны быть сведены к минимуму, чтобы избежать неожиданностей.


Дальнейшее чтение: mailing list thread, где это уже обсуждалось некоторое время назад. Здесь упоминается макроопределение, если вы делаете , а не, необходимо знать тип во время выполнения.