扩展(extension)
扩展是向一个已有的类、结构体或枚举类型添加新的功能。在swift中扩展是没有名字的,
但在Objective-C中Category是有名字的,而且只能扩展类(类别)
如在Swift中扩展是这么写的:
extension String {
func reverseString() -> String {
// do something if necessary
}
}
在Objective-C中,是这么写的:
@interface NSString (ReverseStringExtension)
- (NSString *)reverseString; // implementent in .m file
@end
Swift中扩展可以:
- 添加计算实例属性(computed property)和计算类属性
- 定义实例方法和类方法
- 提供新的构造器
- 定义下标(subscript)
- 定义和使用新的嵌套类型
- 使一个遵守某个接口
扩展语法(Extension syntax)
声明扩展的关键字extension
extension SomteType {
// add sth
}
可以扩展类型时让类型遵守协议:
extension SomteType : SomeProtocol, OtherProtocol {
// do sth if necessary
}
扩展类型,添加计算属性:
// 添加长度单位属性
extension Double {
var km: Double {
return selfself * 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
}
}
let oneInch = 25.4.mm
println("One inch is \(oneInch) meters") // prints One inch is 0.0254 meters
let threeFeet = 3.ft
println("Three feet is \(threeFeet) meters") // prints Three feet is 0.914399970739201 meters
let sum = 10.4.km + 122.5.km // 这么写法是不是很方便就能进行转换?Yes
注意:
扩展可以添加新的计算属性,但不能添加存储属性,也不能向已有属性添加属性观察。
给值类型扩展新的构造器。
如果使用扩展给值类型添加一个构造器,如果该类型所有属性已经有默认值,但没有定制任何构造器,此时我们可以调用默认的构造器和成员逐一构造器。
struct Size {
var width = 0.0
var height = 0.0
}
struct Point {
var x = 0.0
var y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
}
// 这里因为Rect结构体都提供了属性的默认值,它可以自动会有一个默认的构造器和一个成员逐一的构造器,
// 即:init()方法和init(origin:Point, size: Size)
// 那么我们可以直接使用:
let defaultRect = Rect() // 调用默认构造器
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0))
// 下面我们给Rect扩展一个构造器
extension Rect {
init(center: Point, size: Size) {
let originX = center.x - size.width / 2.0
let originY = center.y - size.height / 2.0
// 调用本类自动得到的成员逐一构造器
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
扩展方法:类方法(引用类型)、静态方法(值类型)和实例方法、修改实例方法
extension Int {
// 参数是一个单类型的闭包,没有参数,没有返回值的闭包
func repetions(task: () -> ()) {
for i in 0..self {
task()
}
}
// 仅是例子,这是不好的设计
static func multiply(a: Int, b: Int) -> Int {
return a * b
}
// 要修改Self,就需要是可改类型方法,需要加上关键字mutating
mutating func square() {
self = selfself * self
}
}
let number = 4
number.repetions { // 使用了trailing closure
println("test extension")
}
// test extension
// test extension
// test extension
// test extension
println(Int.multiply(2, 3)) // prints 6
println(3.square()) // prints 9
下标(subscripts)
扩展可以向一个已有类型添加新下标。如下:
extension Int {
// 下标[n]会返回十进制数字从右向左第n个数字
subscript(index: Int) -> Int {
var decimalBase = 1
for _ in 1...index {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}
println(746381295[0])
// returns 5
println(746381295[1])
// returns 9
println(746381295[2])
// returns 2
println(746381295[8])
// returns 7
总结:个人认识扩展是很好用的功能,在项目中,会把通常的基础辅助方法扩展到已有类中, 这样可以方便整个工程的使用。