Haxe允许许多类型的参数化,就像类字段(第4章)和枚举构造函数(第2.4.1节)。类型参数通过闭合的用逗号分隔的类型参数名尖括号来定义。一个简单的例子来自于Haxe标准库,就是 Array:
> Haxe allows parametrization of a number of types, as well as class fields (4) and enum constructors (2.4.1). Type parameters are defined by enclosing comma-separated type parameter names in angle brackets <>. A simple example from the Haxe Standard Library is Array:
~~~
class Array<T> {
function push(x : T) : Int;
}
~~~
每当一个Array的实例被创建,它的类型参数 T 成为一个 单形(第2.9节)。也就是说,它可以被绑定到任何类型,但是一次只有一个。这个绑定可以是显式的发生,通过调用构造函数使用显式的类型(new Array<String>()),或者隐式的发生,通过类型推断(第3.6节),例如当我们调用arrayInstance.push("foo") 。
> Whenever an instance of Array is created, its type parameter T becomes a monomorph (2.9). That is, it can be bound to any type, but only one at a time. This binding can happen
explicitly by invoking the constructor with explicit types (new Array<String>()) or implicitly by type inference (3.6), e.g. when invoking arrayInstance.push("foo").
一个类的定义内部使用类型参数,这些类型参数都是非特定的类型。除非约束(第3.2.1节)被添加,编译器必须假定类型参数可以被和任何类型一起使用。因此,不能访问类型参数的字段或者转换(第5.23)为一个类型参数类型。也不可能创建一个新的类型参数类型的实例,除非类型参数是泛型(第3.3节)并且被相应的约束。
> Inside the definition of a class with type parameters,these type parameters are an unspecific type. Unless constraints (3.2.1) are added, the compiler has to assume that the type parameters could be used with any type. As a consequence, it is not possible to access fields of type parameters or cast (5.23) to a type parameter type. It is also not possible to create a new instance of a type parameter type, unless the type parameter is generic (3.3) and constrained accordingly.
下面的表格显示允许类型参数的地方:
> The following table shows where type parameters are allowed:
|位置|绑定在|注意|
| -- | -- | -- |
|Class|实例化|也可以被绑定到成员字段访问上|
|Enum|实例化||
|Enum构造函数|实例化||
|Function|调用中|允许用于方法和命名的局部 lvalue 函数|
|Structure|实例化||
使用函数类型参数被绑定到调用中,这样一个类型参数(如果无约束)接受任何类型。然而,每次调用只有一个类型被接受。这可以在有多个参数的函数中被利用:
> With function type parameters being bound upon invocation, such a type parameter (if unconstrained) accepts any type. However, only one type per invocation is accepted. This can be utilized if a function has multiple arguments:
~~~
class Main {
static public function main() {
equals(1, 1);
// runtime message: bar should be foo
equals("foo", "bar");
// compiler error: String should be Int
equals(1, "foo");
}
static function equals<T>(expected:T, actual:T) {
if (actual != expected) {
trace(’$actual should be $expected’);
}
}
}
~~~
equals函数所有预期的和实际的参数都有一个类型 T 。这意味着对于每个equals的调用,这两个参数必须是相同类型。编译器承认第一次调用(两种参数类型都是Int)和第二个调用(两个参数都是String),但是第三次尝试引发一个编译器错误。
> Both arguments expected and actual of the equals function have type T. This implies that for each invocation of equals the two arguments must be of the same type. The compiler admits the first call (both arguments being of Int) and the second call (both arguments being of String) but the third attempt causes a compiler error.
**表达式语法中的类型参数**
>[warning] **花絮**:表达式语法中的类型参数
我们经常遇到的问题,为什么一个方法使用类型参数不能被调用为 method<String>(x) 。编译器给出的错误信息不是非常有帮助的。然而,有一个简单的理由:上面的代码如果 < 和 > 都是二元操作符,将被解析产生 (method< Sting)>(x) 。
>[warning] **Trivia**: Type parameters in expression syntax
We often get the question why a method with type parameters cannot be called as method<String>(x). The error messages the compiler gives are not very helpful. However,there is a simple reason forthat: The above code is parsed as if both < and > were binary operators, yielding (method < String) > (x).
- 空白目录
- 1.Haxe介绍
- 1.1.Haxe是什么
- 1.2.关于本文档
- 1.2.1.作者及贡献者
- 1.2.2.License
- 1.3Hello World
- 1.4.Haxe的历史
- 2.类型
- 2.1.基本类型
- 2.1.1.数值类型
- 2.1.2.溢出
- 2.1.3.数值运算符
- 2.1.4.Bool类型
- 2.1.5.Void类型
- 2.2.为空性
- 2.2.1.可选参数和为空性
- 2.3.类实例
- 2.3.1.类的构造函数
- 2.3.2.继承
- 2.3.3.接口
- 2.4.枚举实例
- 2.4.1.Enum构造函数
- 2.4.2.使用枚举
- 2.5.匿名结构
- 2.5.1.结构值的JSON形式
- 2.5.2. 结构类型的类记法
- 2.5.3.可选字段
- 2.5.4.性能影响
- 2.6.函数类型
- 2.6.1.可选参数
- 2.6.2.默认值
- 2.7.动态类型
- 2.7.1.Dynamic使用类型参数
- 2.7.2.实现Dynamic
- 2.8.抽象类型
- 2.8.1.隐式类型转换
- 2.8.2.运算符重载
- 2.8.3.数组访问
- 2.8.4.选择函数
- 2.8.5.枚举抽象类型
- 2.8.6.转发抽象类型字段
- 2.8.7.核心类型抽象
- 2.9.单形
- 3.类型系统
- 3.1.Typedef
- 3.1.1.扩展
- 3.2.类型参数
- 3.2.1.约束
- 3.3.泛型
- 3.3.1.泛型类型参数解释
- 3.4.变异
- 3.5.统一
- 3.5.1.类/接口 之间
- 3.5.2.结构子类型化
- 3.5.3.单形
- 3.5.4.函数返回
- 3.5.5.通用基本类型
- 3.6.类型推断
- 3.6.1.由上而下推断
- 3.6.2.局限
- 3.7.模块和路径
- 3.7.1.模块子类型
- 3.7.2.Import
- 3.7.3.解析顺序
- 4.类字段
- 4.1.变量
- 4.2.属性
- 4.2.1.常见访问标识符组合
- 4.2.2.对类型系统的影响
- 4.2.3.getter和setter的规则
- 4.3.方法
- 4.3.1.重写方法
- 4.3.2.变异和访问修饰符的影响
- 4.4.访问修饰符
- 4.4.1.可见性
- 4.4.2.Inline
- 4.4.3.Dynamic
- 4.4.4.Override
- 4.4.5.Static
- 5.表达式
- 5.1.块
- 5.2.常量
- 5.3.二元操作符
- 5.4.一元操作符
- 5.5.数组声明
- 5.6.对象声明
- 5.7.字段访问
- 5.8.数组访问
- 5.9.函数调用
- 5.10.var
- 5.11.局部函数
- 5.12.new
- 5.13.for
- 5.14.while
- 5.15.do-while
- 5.16.if
- 5.17.switch
- 5.18.try/catch
- 5.19.return
- 5.20.break
- 5.21.continue
- 5.22.throw
- 5.23.类型转换
- 5.23.1.不安全转换
- 5.23.2.安全转换
- 5.24.类型检查
- 6.语言特性
- 6.1.条件编译
- 6.2.Externs
- 6.3.静态扩展
- 6.3.1.标准库中的静态扩展
- 6.4.模式匹配
- 6.4.1.介绍
- 6.4.2.枚举匹配
- 6.4.3.变量捕获
- 6.4.4.结构匹配
- 6.4.5.数组匹配
- 6.4.6.Or 模式
- 6.4.7.守护
- 6.4.8.多个值的匹配
- 6.4.9.提取器
- 6.4.10.穷尽性检查
- 6.4.11.无效的模式检查
- 6.5.字符串插值
- 6.6.数组推导
- 6.7.迭代器
- 6.8.函数绑定
- 6.9.元数据
- 6.10.访问控制
- 6.11.内联构造函数
- 7.编译器用法
- 7.1.编译器标记
- 8.编译器功能
- 8.1.内建编译器元数据
- 8.2.无用代码消除
- 8.3.编译器服务
- 8.3.1.概述
- 8.3.2.字段访问完成
- 8.3.3.调用参数完成
- 8.3.4.类型路径完成
- 8.3.5.使用完成
- 8.3.6.位置完成
- 8.3.7.顶级完成
- 8.3.8.完成服务
- 8.4.资源
- 8.4.1.嵌入资源
- 8.4.2.检索文本资源
- 8.4.3.检索二进制资源
- 8.4.4.实现细节
- 8.5.运行时类型信息
- 8.5.1.RTTI 结构
- 8.6.静态分析仪
- 9.宏
- 9.1.宏上下文
- 9.2.参数
- 9.2.1.ExprOf
- 9.2.2.常数表达式
- 9.2.3.其它的参数
- 9.3.具体化
- 9.3.1.表达式具体化
- 9.3.2.类型具体化
- 9.3.3.类具体化
- 9.4.工具
- 9.5.类型构建
- 9.5.1.枚举构建
- 9.5.2.@:autoBuild
- 9.5.3.@:genericBuild
- 9.6.限制
- 9.6.1.Macro-in-Macro
- 9.6.2.静态扩展
- 9.6.3.构建顺序
- 9.6.4.类型参数
- 9.7.初始化宏
- 10.标准库
- 10.1.字符串
- 10.2.数据结构
- 10.2.1.数组
- 10.2.2.向量
- 10.2.3.列表
- 10.2.4.GenericStack
- 10.2.5.Map
- 10.2.6.Option
- 10.3.正则表达式
- 10.3.1.匹配
- 10.3.2.分组
- 10.3.3.替换
- 10.3.4.分割
- 10.3.5.Map
- 10.3.6.实现细节
- 10.4.Math
- 10.4.1.特殊数值
- 10.4.2.数学错误
- 10.4.3.整数数学
- 10.4.4.扩展
- 10.5.Lambda
- 10.6.模板
- 10.7.反射
- 10.8.序列化
- 10.8.1.格式化序列化
- 10.9.Xml
- 10.9.1.开始使用Xml
- 10.9.2.解析Xml
- 10.9.3.编码Xml
- 10.10.Json
- 10.10.1.解析JSON
- 10.10.2.编码JSON
- 10.10.3.实现细节
- 10.11.Input/Output
- 10.12.Sys/sys
- 10.13.远程处理
- 10.13.1.远程连接
- 10.13.2.实现细节
- 10.14.单元测试
- 11.Haxelib
- 11.1.Haxe编译器使用库
- 11.2.haxelib.json
- 11.2.1.版本控制
- 11.2.2.依赖关系
- 11.3.extraParams.hxml
- 11.4.使用Haxelib
- 12.目标平台细节
- 12.1.JavaScript
- 12.1.1.开始使用Haxe/JavaScript
- 12.1.2.使用外部JavaScript库
- 12.1.3.注入原生JavaScript
- 12.1.4.JavaScript untyped函数
- 12.1.5.调试JavaScript
- 12.1.6.JavaScript目标元数据
- 12.1.7.为JavaScript暴露Haxe类
- 12.1.8.使用 require函数加载外部类
- 12.2.Flash
- 12.2.1.开始使用Haxe/Flash
- 12.2.2.嵌入资源
- 12.2.3.使用外部Flash库
- 12.2.4.Flash目标元数据
- 12.3.Neko
- 12.4.PHP
- 12.4.1.开始使用Haxe/PHP
- 12.4.2.PHP untyped函数
- 12.5.C++
- 12.5.1.Using C++定义
- 12.5.2.Using C++ 指针
- 12.6.Java
- 12.7.C#
- 12.8.Python