定义:
扩展 就是为一个已有的类、结构体、枚举类型或者协议类型添加新功能。这包括在没有权限获取原始源代码的情况下扩展类型的能力(即 逆向建模 )。
扩展可以做什么?
- 添加计算型属性和计算型类型属性
- 定义实例方法和类型方法
- 提供新的构造器
- 定义下标
- 定义和使用新的嵌套类型
- 使一个已有类型符合某个协议
扩展不可以做什么?
- 不能重写已有的功能。
- 不可以添加存储属性。
- 不可以为已有属性添加属性观察器。
- 不能为类添加新的指定构造器或析构器。指定构造器和析构器必须总是由原始的类实现来提供。
注意
1.如果你使用扩展为一个值类型添加构造器,同时该值类型的原始实现中未定义任何定制的构造器且所有存储属性提供了默认值,那么我们就可以在扩展中的构造器里调用默认构造器和逐一成员构造器。如果你把定制的构造器写在值类型的原始实现中,上述规则将不再适用。
2.如果你通过扩展为一个已有类型添加新功能,那么新功能对该类型的所有已有实例都是可用的,即使它们是在这个扩展定义之前创建的。
语法
使用关键字 extension 来声明扩展:
extension SomeType : SomeProtocol,AnotherProtocol {
// 为 SomeType 添加的新功能写到这里
}
计算属性
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 }
}
let length = 5.0.mm
print("5 mm is \(length) m")
构造器
struct Person {
var name : String?
var age : Int?
}
extension Person {
//注意,新的构造器依旧有责任确保构造过程能够让实例完全初始化。
init(_ aName:String,_ aAge:Int) {
self.name = aName
self.age = aAge
}
}
let person = Person.init("Bob", 15)
方法
extension Person {
func printName() {
print(self.name!)
}
}
person.printName() //结果: “Bob”
可变实例方法
通过扩展添加的实例方法也可以修改实例本身。在结构体和枚举类型中修改self或者其属性的方法必须将该实例方法标注为mutating
extension Person {
mutating func changeName() {
self.name = self.name! + " Smith"
}
}
person.changeName()
print(person.name!) //结果:“Bob Smith”