Haxe是一个介于动态语言和静态语言之间的语言,能适应多平台。因此haxe的泛型在各个平台对于编译结果可能会出现各种类型编译错误,因此引入了@:generic元数据,可以强制目标平台多增加一条匹配类型的方法。例如:
@:generic
class MyValue<T> {
public var value:T;
public function new(value:T) {
this.value = value;
}
}
class Main {
static public function main() {
var a = new MyValue<String>("Hello");
var b = new MyValue<Int>(42);
}
}
//---------------------对于JS的编译结果如下-------------------
(function () { "use strict";
var Test = function() { };
Test.main = function() {
var a = new MyValue_String("Hello");
var b = new MyValue_Int(5);
};
var MyValue_Int = function(value) {//注意方法后缀
this.value = value;
};
var MyValue_String = function(value) {//注意方法后缀
this.value = value;
};
Test.main();
})();
//--------------------如果我把元数据去掉,结果如下--------------
(function () { "use strict";
var MyValue = function(value) {
this.value = value;
};
var Main = function() { };
Main.main = function() {
var a = new MyValue("Hello");//可能就会出问题
var b = new MyValue(42);
};
Main.main();
})();
也可以用于单个方法上:
class Main {
static public function main() {
method("foo");
method(1);
}
@:generic static function method<T>(t:T) { }
}
--------------------------------------
编译器只能认一个实际的对象,因此不用泛型产生一个实际对象,如: new T()
会产生编译错误。但是可以用@:generic做到这种事情。
import haxe.Constraints;
class Main {
static public function main() {
var s:String = make();
var t:haxe.Template = make();
}
@:generic
static function make<T:Constructible<String->Void>>():T {
return new T("foo");
}
}
需要注意的是,这里使用自上而下的推理来确定T的实际类型,要做到这个事情有两个条件:
1、要用generic关键字
2、必须严格限制参数:给定参数真实类型。