类型别名
当某个类型的名字比较复杂或者在特定场景中不够直观时,可以选择使用类型别名的方式为此类型设置一个别名。
type I64 = Int64
类型别名的定义以关键字 type
开头,接着是类型的别名(如上例中的 I64
),然后是等号 =
,最后是原类型(即被取别名的类型,如上例中的 Int64
)。
只能在源文件顶层定义类型别名,并且原类型必须在别名定义处可见。例如,下例中 Int64
的别名定义在 main
中将报错,LongNameClassB
类型在为其定义别名时不可见,同样报错。
main() {
type I64 = Int64 // Error, type aliases can only be defined at the top level of the source file
}
class LongNameClassA { }
type B = LongNameClassB // Error, type 'LongNameClassB' is not defined
一个(或多个)类型别名定义中禁止出现(直接或间接的)循环引用。
type A = (Int64, A) // Error, 'A' refered itself
type B = (Int64, C) // Error, 'B' and 'C' are circularly refered
type C = (B, Int64)
类型别名并不会定义一个新的类型,它仅仅是为原类型定义了另外一个名字,它有如下几种使用场景:
-
作为类型使用,例如:
type A = B class B {} var a: A = B() // Use typealias A as type B
-
当类型别名实际指向的类型为 class、struct 时,可以作为构造器名称使用:
type A = B class B {} func foo() { A() } // Use type alias A as constructor of B
-
当类型别名实际指向的类型为 class、interface、struct 时,可以作为访问内部静态成员变量或函数的类型名:
type A = B class B { static var b : Int32 = 0; static func foo() {} } func foo() { A.foo() // Use A to access static method in class B A.b }
-
当类型别名实际指向的类型为 enum 时,可以作为 enum 声明的构造器的类型名:
enum TimeUnit { Day | Month | Year } type Time = TimeUnit var a = Time.Day var b = Time.Month // Use type alias Time to access constructors in TimeUnit
需要注意的是,当前用户自定义的类型别名暂不支持在类型转换表达式中使用,参考如下示例:
type MyInt = Int32
MyInt(0) // Error, no matching function for operator '()' function call
泛型别名
类型别名也是可以声明类型形参的,但是不能对其形参使用 where
声明约束,对于泛型变元的约束我们会在后面给出解释。
当一个泛型类型的名称过长时,我们就可以使用类型别名来为其声明一个更短的别名。例如,有一个类型为 RecordData
,我们可以把他用类型别名简写为 RD
:
struct RecordData<T> {
var a: T
public init(x: T){
a = x
}
}
type RD<T> = RecordData<T>
main(): Int64 {
var struct1: RD<Int32> = RecordData<Int32>(2)
return 1
}
在使用时就可以用 RD<Int32>
来代指 RecordData<Int32>
类型。