扩展就是为一个已有的类、结构体、枚举类型或者协议类型添加新功能。这包括在没有权限获取源码的情况下扩展类型的能力(即 逆向建模)。扩展和OC中的分类类似。(与OC不同的是,Swift的扩展没有名字)。
Swift中的扩展可以
- 添加计算型属性和计算型类型属性。
- 定义实例方法和类型方法
- 提供新的构造器
- 定义下标
- 定义和使用新的嵌套类型
- 使一个已有类型符合某个协议
扩展语法
使用关键字extension
来声明扩展
extension SomeType{
//为someType添加新功能
}
可以通过扩展来扩展一个已有类型,使其采纳一个或多个协议。在这种情况下,无论是类还是结构体,协议名字的书写方式完全一样。
extension SomeType : SomeProtocol, AnotherProtocol{
//协议实现写在这里
}
如果通过扩展为一个已有类型添加新功能,那么新功能对该类型的所有已有实例都是可用的,即使它们是在这个扩展定义之前创建的。
计算型属性
扩展可以为已有类型添加计算型实例属性
和计算型类型属性
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 / 1000.0 }
var ft: Double { return self / 3.28084 }
}
let oneinch = 25.4.mm;
print(oneinch);//输出0.0254;
这些计算型属性
表达的含义是把一个 Double 值看作是某单位下的长度值。即使它们被实现为计算型属性
,但这些属性的名字仍可紧接一个浮点型字面值,从而通过点语法
来使用,并以此实现距离转换。
注意:扩展可以添加新的计算型属性,但是不可以添加存储型属性,也不可以为已有属性添加属性观察器。
构造器
扩展可以为已有类型添加新的构造器。这可以让你扩展其他类型,将你自己的定制类型作为其他构造器参数,或者提供该类型的原始实现中未提供的额外初始化选项。
扩展能为类添加新的便利构造器,但是他们不能为类添加新的指定构造器或析构器。指定构造器和西枸杞必须总是由原始的类实现来提供。
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)
}
}
这个新的构造器首先根据提供的 center 和 size 的值计算一个合适的原点。
然后调用该结构体的逐一成员构 造器 init(origin:size:)
该构造器将新的原点和大小的值保存到了相应的属性中:
方法
扩展可以为已有类型添加新的实例方法
和类型方法
。
extension Int{
func repetitions(task: () -> Void) -> Void{
for _ in 0..<self {
task();
}
}
}
//执行3次闭包方法
3.repetitions(task: {
print("hello");
})
- 可变方法实例
通过扩展添加的实例方法也可以修改该实例本身。结构体和枚举类型中修改self
或其属性的方法必须将该实例方法标注为mutating
,正如来自原始实现的可变方法一样。
extension Int {
mutating func square() {
self = self * self;//计算平方
}
}
var someInt = 3;
someInt.square()
print(someInt);//此时someint的值为9;