拓展
扩展就是向一个已有的类、结构体或枚举类型添加新功能(functionality)。这包括在没有权限获取原始源代码的情况下扩展类型的能力(即逆向建模)。扩展和 Objective-C中的分类(categories)类似。(不过与Objective-C不同的是,Swift的扩展没有名字。
extension SomeType { // 加到SomeType的新功能写到这里 }按以下方式添加的协议遵循者( protocol conformance )被称之为在扩展中添加协议遵循者
extension SomeType: SomeProtocol,AnotherProctocol { // 协议实现写到这里 }计算型属性
extension Double { var km: Double { return self * 1_000.0 } var m : Double { return self } var cm: Double { return self / 100.0 } var mm: Double { return self / 1_000.0 } var ft: Double { return self / 3.28084 } }<pre name="code" class="plain">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() } let defaultRect = Rect() let memberwiseRect = Rect(origin: Point(x: 2.0,y: 2.0),size: Size(width: 5.0,height: 5.0)) 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) } } let centerRect = Rect(center: Point(x: 4.0,y: 4.0),size: Size(width: 3.0,height: 3.0)) // centerRect的原点是 (2.5,2.5),大小是 (3.0,3.0)
let oneInch = 25.4.mmprintln("One inch is \(oneInch) meters")// 打印输出:"One inch is 0.0254 meters"let threeFeet = 3.ftprintln("Three feet is \(threeFeet) meters")// 打印输出:"Three feet is 0.914399970739201 meters"let aMarathon = 42.km + 195.mprintln("A marathon is \(aMarathon) meters long")// 打印输出:"A marathon is 42495.0 meters long"
注意:扩展可以添加新的计算属性,但是不可以添加存储属性,也不可以向已有属性添加属性观测器(property observers)。
构造器(Initializers)
扩展可以向已有类型添加新的构造器。这可以让你扩展其它类型,将你自己的定制类型作为构造器参数,或者提供该类型的原始实现中没有包含的额外初始化选项。
如果你使用扩展向一个值类型添加一个构造器,该构造器向所有的存储属性提供默认值,而且没有定义任何定制构造器(custom initializers),那么对于来自你的扩展构造器中的值类型,你可以调用默认构造器(default initializers)和成员级构造器(memberwise initializers)。 正如在值类型的构造器授权中描述的,如果你已经把构造器写成值类型原始实现的一部分,上述规则不再适用。
如果你使用扩展提供了一个新的构造器,你依旧有责任保证构造过程能够让所有实例完全初始化
extension Int { func repetitions(task: () -> ()) { for _ in 0..<self { task() } } }
这个repetitions方法使用了一个() -> ()类型的单参数(single argument),表明函数没有参数而且没有返回值。
3.repetitions({ println("Hello!") }) // Hello!!! // Hello!!! // Hello!!!使用 trailing 闭包使调用更加简洁
3.repetitions{ println("Goodbye!") } // Goodbye! // Goodbye! // Goodbye!
通过扩展添加的实例方法也可以修改该实例本身。结构体和枚举类型中修改self或其属性的方法必须将该实例方法标注为mutating
extension Int { mutating func square() { self = self * self } } var someInt = 3 someInt.square() //someInt此时的值为9
子脚本
扩展可以向一个已有类型添加新下标
extension Int { subscript(var digitIndex: Int) -> Int { var decimalBase = 1 while digitIndex > 0 { decimalBase *= 10 --digitIndex } return (self / decimalBase) % 10 } } 746381295[0] // returns 5 746381295[1] // returns 9 746381295[2] // returns 2 746381295[8] // returns 7
如果该Int值没有足够的位数,即下标越界,那么上述实现的下标会返回0,因为它会在数字左边自动补0:
//746381295[9] returns 0,即等同于:0746381295[9]
嵌套类型
扩展可以向已有的类、结构体和枚举添加新的嵌套类型
向Int中添加了嵌套枚举
extension Int { enum Kind { case Negative,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("- ") case .Zero: print("0 ") case .Positive: print("+ ") } } print("\n") } printIntegerKinds([3,19,-27,-6,7]) // prints "+ + - 0 - 0 +"
注意:number.kind是已知的Int.kind类型,正因为如此,所有的Int.kind成员值可以用简写形式在switch语句中.