typealias
1 2 3 4 5 6 7 8 9 10
| func distanceBetweenPoint(point: CGPoint, toPoint: CGPoint) -> Double { let dx = Double(toPoint.x - point.x) let dy = Double(toPoint.y - point.y) return sqrt(dx * dx + dy * dy) }
let origin: CGPoint = CGPoint(x: 0, y: 0) let point: CGPoint = CGPoint(x: 1, y: 1)
let distance: Double = distanceBetweenPoint(origin, point)
|
typealias用来为已经存在的类型重新定义名字,通过命名可以使代码变得更加清晰。比如上段代码,我们用 Double 表示距离,用 CGPoint 表示位置。
虽然在数学上和最后运行上兵没有问题,但是阅读和维护的时候就会产生障碍。CGPoint 代表一个点,这个点是我们定义的坐标系里的位置; Double 是一个数字,它代表两个点之间的距离。
如果使用typealias,代码就会变成如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| typealias Location = CGPoint typealias Distance = Double
func distanceBetweenPoint(location: Location, toLocation: Location) -> Distance { let dx = Distance(location.x - toLocation.x) let dy = Distance(location.y - toLocation.y) return sqrt(dx * dx + dy * dy) }
let origin: Location = Location(x: 0, y: 0) let point: Location = Location(x: 1, y: 1)
let distance: Distance = distanceBetweenPoint(origin, point)
|
当遇到复杂的实际问题时,你将不在关心 Int 或者 String这类基本类型代表什么。
typealias 在泛型中的作用
首先,typealias 是单一的,你必须指定将某个特定类型通过 typealias 赋值为新名字,而不能将整个泛型类型重命名。下面的代码是无法通过编译的:
1 2 3 4 5
| class Person<T> {} typealias Worker = Person typealias Worker = Person<T> typealias Worker<T> = Person<T>
|
一旦泛型类型的确定性得到保证后,就可以重命名了:
1 2 3 4
| class Person<T> {}
typealias WorkId = String typealias Worker = Person<WorkId>
|
typelias 在泛型接口中的使用
swift 中是没有泛型接口的,但是使用 typealias,我们可以在接口里定义一个必须实现的别名。比如 GeneratorType 和 SequenceType 这两个接口中,都用 typealias 来确定一个使用协议的类的唯一性:
1 2 3 4 5 6 7 8 9 10 11
| protocol GeneratorType { typealias Element mutating func next() -> Element? }
public protocol SequenceType { typealias Generator : GeneratorType typealias SubSequence }
|
就是说,在遵守 GeneratorType 和 SequenceType 两个协议的时候,通过在里头声明一个 typealias,这个类型别名 Element 是啥,需要由其实现者去填写