听起来您的问题主要是关于运行时类型识别 (RTTI) 和类型转换。 Haxe 在Type 和Reflect 类中提供了许多实用程序来处理这个问题。
对于您的代码,您似乎特别想要:
if (Std.is(target, Foo)) (cast target:Foo).aFooMethod();
else if (Std.is(target, Bar)) (cast target:Bar).aBarMethod();
或许:
if (Std.is(target, Foo)) {
var targetAsFoo:Foo = cast target;
targetAsFoo.aFooMethod();
} else if (Std.is(target, Bar)) {
var targetAsBar:Bar = cast target;
targetAsBar.aBarMethod();
}
这是一个示例,展示了许多可以帮助您的实用程序,包括Std.is、接口、Type.getClass、类型转换等:http://try.haxe.org/#3C192
代码如下:
class Test {
static function main() {
function identify(tgt:Dynamic)
{
trace("1: "+tgt);
trace("2: "+Type.typeof(tgt));
trace("3: "+Type.getClassName(tgt));
trace("4: "+Type.getClass(Type.getClassName(tgt)));
trace("5: "+Std.is(tgt, Something));
if (Std.is(tgt, Something)) {
// Can cast explicitly
var casted:Something = cast tgt;
trace("Got a Something named: "+casted.name);
}
if (Std.is(tgt, Something)) {
// Can cast implicitly
var casted:Something = untyped tgt;
trace("Got a Something named: "+casted.name);
}
if (Std.is(tgt, Something)) {
// Can cast in an inline style, (obj:Type)
trace("Got a Something named: "+(tgt:Something).name);
}
if (Std.is(tgt, IHasAName)) {
// Can cast to an interface, if you prefer
var i_casted:IHasAName = (tgt:IHasAName);
trace("Got a IHasAName named: "+i_casted.name);
}
// Can reflect to see if the name field exists:
if (Reflect.hasField(tgt, "name")) {
trace("tgt has a name: "+Reflect.field(tgt, "name"));
}
if (Reflect.hasField(tgt, "length")) {
trace("tgt has a length: "+Reflect.field(tgt, "length"));
}
}
trace("----------------------------------");
trace("Calling identify with a Something:");
trace("----------------------------------");
var a = new Something("foo", 3);
identify(a);
trace("----------------------------------");
trace("Calling identify with a String:");
trace("----------------------------------");
var b = "a string";
identify(b);
trace("----------------------------------");
trace("Calling identify with anonymous:");
trace("----------------------------------");
var c = { "name" : "anonymous" };
identify(c);
}
}
class Something implements IHasAName
{
public var name:String;
public var length:Int;
public function new(name:String, length:Int)
{
this.name = name;
this.length = length;
}
}
interface IHasAName {
public var name:String;
}
输出是:
14:41:24:664 ----------------------------------
14:41:24:664 Calling identify with a Something:
14:41:24:664 ----------------------------------
14:41:24:664 1: { name : foo, length : 3 }
14:41:24:665 2: TClass({ __name__ : [Something] })
14:41:24:665 3: null
14:41:24:665 4: null
14:41:24:665 5: true
14:41:24:665 Got a Something named: foo
14:41:24:665 Got a Something named: foo
14:41:24:665 Got a Something named: foo
14:41:24:665 Got a IHasAName named: foo
14:41:24:665 tgt has a name: foo
14:41:24:665 tgt has a length: 3
14:41:24:666 ----------------------------------
14:41:24:666 Calling identify with a String:
14:41:24:666 ----------------------------------
14:41:24:666 1: a string
14:41:24:666 2: TClass({ __name__ : [String] })
14:41:24:666 3: null
14:41:24:666 4: null
14:41:24:666 5: false
14:41:24:666 tgt has a length: 8
14:41:24:667 ----------------------------------
14:41:24:667 Calling identify with anonymous:
14:41:24:667 ----------------------------------
14:41:24:667 1: { name : anonymous }
14:41:24:667 2: TObject
14:41:24:667 3: null
14:41:24:668 4: null
14:41:24:668 5: false
14:41:24:668 tgt has a name: anonymous
我隐约记得在 actionscript 3 中能够使用 target.name 但在这种情况下返回 null。
在 AS3 中,event.target 的类型为 DisplayObject,而所有 DisplayObjects have a .name property,这就是您可以在 AS3 中这样做的原因。
OpenFL 的 Event.target 是一个 IEventDispatcher,它与显示类没有特别关联。