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);
}
~~~
- 本書目錄
- 第一章:Haxe介紹
- 互聯網開發的一個問題
- Haxe是什么,為什么產生
- Haxe編譯工具
- Haxe語言
- Haxe如何工作
- 那么Neko是什么
- Haxe和Neko的必須條件
- 本章摘要
- 第二章:安裝、使用Haxe和Neko
- 安裝Haxe
- 使用Haxe安裝程序
- 在Windows上手動安裝Haxe
- Linux上手動安裝Haxe
- 安裝Neko
- Windows上手動安裝Neko
- 在Linux上安裝Neko
- Hello world! 一式三份
- 編譯你的第一個Haxe應用
- 你的程序如何編譯
- HXML編譯文件
- 編譯到Neko
- 編譯為JavaScript
- 程序結構
- 編譯工具開關
- 本章摘要
- 第三章:基礎知識學習
- Haxe層級結構
- 標準數據類型
- 變量
- 類型推斷
- 常數變量
- 簡單的值類型
- 浮點類型
- 整型
- 選擇數值類型
- 布爾類型
- 字符串類型
- 抽象類型
- Void 和 Null
- 動態類型
- unknown類型
- 使用untyped繞過靜態類型
- 注釋代碼
- 轉換數據類型
- Haxe數組
- Array
- List
- Map
- Haxe中使用日期時間
- 創建一個時間對象
- Date組件
- DateTools類
- 操作數據
- 操作符
- Math類
- 使用String函數
- 本章摘要
- 第四章:信息流控制
- 數據存放之外
- 條件語句
- if語句
- switch語句
- 從條件語句返回值
- 循環
- while循環
- for循環
- 循環集合
- Break和Continue
- 函數
- 類的函數
- 局部函數
- Lambda類
- 本章摘要
- 第五章:深入面向對象編程
- 類和對象
- 實例字段
- 靜態字段
- 理解繼承
- Super
- 函數重載
- 構造器重載
- toString()
- 抽象類和抽象方法
- 靜態字段,實例變量和繼承
- 繼承規則
- 使用接口
- 高級類和對象特性
- 類的實現
- 類型參數
- 匿名對象
- 實現動態
- Typedef
- 擴展
- 枚舉
- 構造器參數
- 本章摘要
- 第六章:組織你的代碼
- 編寫可重用代碼
- 使用包
- 聲明一個包
- 隱式導入
- 顯式導入
- 枚舉和包
- 類型查找順序
- 導入一個完整的包
- 導入庫
- Haxe標準庫
- Haxelib庫
- 其他項目中的庫
- 外部庫
- 使用資源
- 文檔化代碼
- 離線文檔
- 在線文檔
- 單元測試
- haxe.unit包
- 編寫測試
- 本章摘要
- 第七章:錯誤調試
- trace函數
- trace輸出
- haxe的trace和ActionScript的trace
- 異常
- 異常處理
- CallStack和ExceptionStack
- 異常管理類
- 創建完全的異常處理類
- 異常類代碼
- 本章摘要
- 第八章:跨平臺工具
- XML
- XML剖析
- Haxe XML API
- 正則表達式
- EReg類
- 模式
- 定時器
- 延遲動作
- 隊列動作
- MD5
- 本章摘要
- 第九章:使用Haxe構建網站
- Web開發介紹
- Web 服務器
- 使用Web服務器發布內容
- HTML速成課程
- Haxe和HTML的區別
- NekoTools Web Server
- Apache安裝mod_neko
- Windows安裝Apache和mod_neko
- Linux安裝Apache和Mod_Neko
- 第一個Haxe網站
- 使用Neko作為網頁Controller
- neko.Web類
- Neko作為前端控制器
- 本章摘要
- 第十章:使用模板進行分離式設計
- 什么是模板
- Template類
- Template語法
- 使用資產
- 何時在模板中使用代碼
- 服務器端模板的Templo
- 安裝Templo
- 使用Templo
- haxe.Template和mtwin.Templo表達式上的區別
- Attr表達式
- Raw表達式
- 邏輯表達式
- 循環表達式
- set, fill, 和 use表達式
- Templo中使用宏
- 手動編譯模版
- 第十一章:執行服務端技巧
- 第十二章:使用Flash構建交互內容
- 第十三章:使用IDE
- 第十四章:通過JavaScript制作更多交互內容
- 第十五章:通過Haxe遠程通信連接所學
- 第十六章:Haxe高級話題
- 第十七章:Neko開發桌面應用
- 第十八章:用SWHX開發桌面Flash
- 第十九章:多媒體和Neko
- 第二十章:使用C/C++擴展Haxe
- 附加部分