多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
Typedef 是一个定义用于匿名类型类型检查的类型的构造。Typedef 声明必须使用如下语法: ~~~ typedef Name = typedeclaration ~~~ Name必须遵守和类名相同的命名规则, typedeclaration 是类型定义的签名。 最常见的用法关于 typedef 是给一个匿名对象以形式的表现。 ~~~ typedef Color = { r: Int, g: Int, b: Int} ~~~ 这样使用: ~~~ var white : Color = { r: 255, g: 255, b: 255 }; ~~~ typedef hi可以用来定义其他类型,如函数或者已有定义的快捷方式。 ~~~ typedef GenericFunction < T > = Void - > T typedef IntArray = Array < Int > typedef P = Person typedef TS = ThreeState enum ThreeState { Checked; Unchecked; Indeterminated; } class Person { public var name : String; public function new() { } } ~~~ 当声明一个匿名对象的类型,有两种语法的可能: ~~~ typedef A = { var x : Float; var y : Float; } typedef B = { x : Float, y : Float } ~~~ 这种情况下,声明是等价的,但是你可以发现不同于一个包含至少有一个函数定义的 typedef : ~~~ typedef A = { function say(text : String) : String; } typedef B = { say : String - > String } ~~~ 在这种情况,两个几乎一样,唯一区别是函数参数在第一个声明被命名,而第二个则匿名。另外的不同是第一个格式里可以添加 private/public 访问修饰符(默认总是 public )。 typedef 还可以有类型参数,和类跟接口类似。 ~~~ typedef Leaf < T > = { parent : Node < T > , data : T } ~~~ typedef 语法是一个重要的Haxe语言特性。 typedef 在很多方面是一个灵活的接口替代选择。typedef验证只在编译时发生并且知识结构上检查;编译器检查传递的对象有需要的字段但是不假设对象的类型定义。这创造了有趣的可能性,下面的例子,handle() 函数接受一个HashNme类型的参数。HasName是一个 typedef,定义它的类型的值必须有一个String类型的name字段。好处是不只是匿名对象可以满足这个结构要求,而类的实例同样可以。 ~~~ class Person { public var name : String; public function new(n : String) { name = n; } } class Item { public var name : String; public var price : Float; public function new(n : String, p : Float) { name = n; price = p; } } typedef HasName = { name : String } class Main { public static function handle(o : HasName) { trace(o.name); } public static function main() { var person = new Person(“John”); var item = new Item(“Laptop PC”, 999.9); var user = { name : “Jane” }; handle(person); handle(item); handle(user); } } ~~~ 你可以简化声明移除 typedef 定义并且替换处理声明通过如下行: ~~~ public static function handle(o : { name : String}) ~~~ typedef并不是嵌入到生成的输出中,而是只用于类型在编译时的检查。他们执行了一种基于惯例的编程,开发人员需要构造带有某些特征的结构但并不需要绑定到类似接口或者基类的形式定义。可以定义一个约定对于一个项目,而不用提供任何代码让同僚实现一个完整的应用。这可以在Web开发环境中带来很大的好处,通常有许多库可以帮助我们工作。 不仅使用在对象,而且任何类型定义都可以使用。举个有趣的例子,有一个函数接收另一个函数作为参数;参数可能是一个内联函数,一个对象方法,或者一个类静态函数。这里有一个例子: ~~~ class StringDecoration { var prefix : String; public function new(prefix : String) { this.prefix = prefix; } public function decorate(s : String) { return prefix + s; } } class Main { public static function print(s : String, decorate : String -> String) { var o = decorate(s); trace(o); } public static function quote(s : String) { return ‘”’ + s + ‘”’; } public static function main() { var decorator = new StringDecoration(“- > “); var s = “John”; print(s, quote); // traces “John” print(s, decorator.decorate); // traces - > John print(s, function(s){ return “-- “ + s + “ --”; }); // traces -- John - } } ~~~ print()的第二个参数是一个typedef对一个接收一个字符串作为参数并返回一个String的函数。在 main() 方法,pirnt()函数用来传递静态函数 quote(),然后类StringDecoration的实例函数 decorate(),最后一个内联函数定义。 # 迭代器和可迭代性 * * * * * 在Haxe标准库中,两个非常常用的typedef是:Iterator<T> 和 Iterable<T>。 它们的定义如下: ~~~ typedef Iterator < T > = { function hasNext() : Bool; function next() : T; } typedef Iterable < T > = { function iterator() : Iterator < T > ; } ~~~ 因为在第三章已经了解过,这些结构被定义来处理对象集合,他们很容易的实现在类定义中。这个例子里,一个随机的迭代器被定义。迭代器会返回一个n个随机字符的序列。 ~~~ class RandomSequence { private var letters : Int; private var counter : Null < Int > ; public function new(letters : Int) { this.letters = letters; } public function hasNext() : Bool { if(counter == null) { // the iterator has to be initialized counter = 0; } if(counter < letters) { return true; } else { // before returning false, the counter variable must // be reset in case the instance has to be used again counter = null; return false; } } public function next() : String { counter++; return Std.chr(Std.int(Math.random() * 26)+ 65); } } ~~~ 代码不显式声明,它是实现Iterator typedef 。这个隐式发生因为类定义正确的方法。这个类这样使用: ~~~ class Main { static function main() { var sequence = new RandomSequence(10); for(letter in sequence) { trace(letter); } } } ~~~ 这个例子会输出十次随机字母。 在实践中Haxe在背后做的死改变 for(序列中的字母)声明: ~~~ while(sequence.hasNext()) { var letter = sequence.next(); // ... } ~~~ 这自动发生每次一个用在for语句中的对象符合 Iterator<T> typedef 。相同的处理是被保留对符合Iterable<T>的对象。这可以用在当对象可以返回一个结合但是有一个间接的中介。 Array<T>是 Iterable<T>,可以用来演示它的用法。下面的两个声明实际上是相同的;编译器在内部改变第二个使其表现的像第一个。 ~~~ for(i in [1,2,4,8].iterator()) { trace(i); } for(i in [1,2,4,8]) { trace(i); } ~~~