概要
扩展是给已经存在的类(class),结构体(structure),枚举类型(enumeration)和协议(protocol)增加新的功能。类似Objective-C中的Category,不同的是,Extension没有名字。扩展可以做以下事情:
- 增加计算实例属性和计算类型属性
- 定义实例方法和类型方法
- 提供新的初始化器
- 定义下标
- 定义和使用新的内置类型
- 让一个存在的类型服从一个协议
注:扩展可以增加新的功能,但是不能覆盖已有的功能
扩展的语法
使用extension关键字,如下所示。
extension SomeType{
//new functionality to add to SomeType goes here
}
extension SomeType: SomeProtocol, AnotherProtocol{
//implementation of protocol requirements goes here
}
注意:如果你给已经存在的类型扩展了新的功能,不管你在什么时候扩展,尽管你是在实例定义之后再扩展的,那么这个类型所有的实例都可以使用这个新功能,
计算属性
扩展可以给已经存在的类型增加计算实例属性和计算类型属性,如以下扩展了Double类型:
extension Double{
var km : Double { return self * 1000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1000.0 }
var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm;
print("One inch is \(oneInch)meters")
构造方法(Initializers)
可以扩展一个类型实现自定义构造方法,但是只能增加便利构造方法(Convenience Initializers),不能增加指定构造方法(Designated Initializers)。
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
}
Rect
结构体没有自定义的构造方法,因为其属性都有初始值,所以系统提供了一个默认构造方法和逐一成员构造方法,在增加构造方法时,可以调用逐一成员构造方法。要确保类型中所有的存储属性都有初始值。
extension Rect{
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
方法
扩展可以增加实例方法和类型方法,如下所示。
extension Int{
funcrepetitions(task: () -> Void) {
for _ in 0..<self {
task()
}
}
}
4.repetitions { //尾随闭包
print("hello")
}
可变实例方法(Mutating Instance Methods)
扩展增加的实例方法可以修改实例本身。结构体和枚举类型中的方法如果想要修改实例本身或者属性的话需要用mutating
来修饰方法,所以扩展这样的方法也需要加mutating
。
extension Int{
mutating func square() {
self = self * self
print(self)
}
}
var someInt = 3
someInt.square()
下标
扩展可以给存在的类型增加新的下标,如下的例子:
extension Int{
subscript(digitIndex: Int) -> Int {
var decimalBase = 1
for _ in 0..<digitIndex {
decimalBase *= 10
}
return(self/ decimalBase) % 10
}
}
746381295[0] // returns 5
746381295[1] // returns 9
746381295[2] // returns 2
746381295[8] // returns 7
内置类型
扩展可以给存在的类、结构体和枚举类型增加新的内置类型。
extension Int{
enumKind {
casenegative, zero, positive
}
var kind: Kind {
switch self {
case 0:
return .zero
case let x where x > 0:
return .positive
default:
return .negative
}
}
}
func printIntegerKinds(_numbers: [Int]) {
for number in numbers {
switch number.kind {
case .negative:
print("-", terminator: "")
case .zero:
print("0", terminator: "")
case .positive:
print("+", terminator: "")
}
}
print("")
}
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
// Prints "+ + - 0 - 0 +