运用扩展能够给现已存在的类添加新的办法,尤其是你对某个类没有控制权的时分。扩展非常有用,尤其是帮你安排你的代码的时分。
什么是扩展
Swift的类、结构体、枚举或者协议都能够运用扩展来添加新的办法。即便这些类型不在你的控制范围内。如:
class Airplane {
var altitude: Double = 0
func setAltitude(feet: Double) {
altitude = feet
}
}
有人想运用单位英尺来描绘altitude
,有人想用单位米。假如这段代码你无法修正,你也不想承继这个类你就能够新建一个扩展。比方:
extension Airplane {
func setAltitude(meter: Double) {
altitude = meter * 3.28084
}
}
这样就能够在一个Airplane
的目标上运用办法setAltitude
了。如:
let boeing = Airplane()
boeing.setAltitude(meter: 12000)
print(boeing.altitude) // Output: 39370.08
扩展在编译的时分,扩展都会和原来的类整合到一同。
所以Swift的扩展能够:
- 添加办法和核算特色
- 供给新的初始化办法
- 运用
subscript()
界说下标 - 添加嵌套类型
- 完成某些协议,这很有用
- 运用协议扩展给协议添加默许完成
扩展尽管好用,可是无法改变一个类(结构体)的基本结构。只能用来添加功用,而不是替换。因而不能给一个类型添加新的特色,比方下面的比方这样是不行的:
extension Airplane {
var speed: Int = 0
}
为什么不能够呢。由于给一个类型添加特色破坏了类型的结构。而且原本就能够经过承继的方法来更改类型的结构。
扩展的别的一个优点是,它能够协助安排好你的代码等各种实践可操作性的特色。比方:
- 别离、安排代码
- 能够运用协议共同性
- 命名空间常量
- 添加办法、特色
- 扩展协议
咱们一条一条来距离阐明
别离、安排代码
运用扩展能够把一个类的代码别离,安排成不同的部分。比方在这通用类的部分只保留特色,在扩展里面添加办法。
比方:
class Airplane
{
var speed: Double = 0
var altitude: Double = 0
var bearing: Double = 0
}
之后运用不同的扩展。首要:
extension Airplane
{
func changeAltitude(altitude: Double) {
self.altitude = altitude
}
func changeBearing(degrees: Double) {
self.bearing = degrees
}
}
然后让飞机能够起飞和着陆:
extension Airplane
{
func takeOff()
{
// Do take-off magic…
}
func land()
{
// Please stow hand luggage and move your seat to an upright position…
}
}
每个扩展能够有他们独立的文件,假如一个文件开始膨胀的时分,最好把他们依照功用放到不同的当地。比方,你新添加了一个view controller。它有两个主要功用,你能够把这两个功用放在两个扩展里。那个view controller能够持续当做一个完好的来运用。
运用协议共同性
你能够运用扩展让原来的类型恪守某一个协议。比方:
class DetailViewController: UIViewController
{
// Do view controller magic…
}
extension DetailViewController: CLLocationManagerDelegate
{
// Put all location code in here…
}
在上面的代码里,DetailViewController
恪守了CLLocationManagerDelegate
协议,你能够放心的在这个扩展里添加代码了。
有一点要记住。扩展可不是你不合理的规划代码的接口。一个巨大的类分割成十个扩展仍是一个巨大的类。合理的规划才是重中之重!
命名空间常量和嵌套类型
运用扩展能够添加静态常量和嵌套类型。
例如:
extension Notification.Name {
static let statusUpdated = Notification.Name(“status_updated”)
}
以上的代码扩展了Notification.Name
,添加了statusUpdated
常量。能够这样运用:NotificationCenter.default.post(name: .statusUpdated, object: nil)
。
post(name:object:)
办法需要Notification.Name
的一个值作为第一个参数,这儿就运用了刚刚添加的statusUpdated
。
添加嵌套类型:
extension UserDefaults
{
struct Keys
{
static let useSync = “use_sync”
static let lastSync = “last_sync”
}
}
能够这样运用:
UserDefaults.default.set(true, forKey: UserDefaults.Keys.useSync)
这样有两个优点:
-
Keys
嵌套类型只会在UserDefaults
类型里能够用。你不必忧虑会有什么类型的重名问题。这样的操作也很类似于其他语言里的类级别命名空间。 - 在
UserDefaults
里运用的时分,假如直接输入use_sync
常量的话也不必忧虑系统提示会提示到什么其他当地界说的常量。
扩展核算特色和办法
这儿举一个栗子。在Swift 4.2的时分数组没有shuffled()
办法。 承继数组能够添加这么一个办法,也能够运用大局办法处理数组。可是运用扩展能够直接给数组添加这个办法了。如:
extension Array
{
func shuffled() {
// Shuffle array items and return shuffled array
}
}
这样shuffled()
办法就能够在恣意的数组上运用了。
另一个很有协助的比方:
class Circle {
var radius: Double = 0
}
extension Circle
{
var circumference:Double {
return radius * .pi * 2
}
}
上面的代码首要界说了一个Circle
类,然后经过扩展给这个类添加了一个核算特色circumference
。能够这样运用这个特色:
let circle = Circle()
circle.radius = 10
print(circle.circumference) // Output: 62.83185307179586
扩展协议
不同于协议共同(如上),协议扩展能够直接对一个协议进行扩展。能够在扩展协议的时分添协议的默许完成。
例如:
protocol Edible {
func eat()
}
协议Edible
里界说了办法eat
,每个恪守这个协议的类型都要完成eat()
办法,例如:
class Fish: Edible
{
func eat() {
print(“**CHOMP** **CRUNCH** Eating the fish…”)
}
}
下面来经过扩展Edible
协议给它添加一个默许完成:
extension Edible
{
func eat() {
print(“Eating the thing…”)
}
}
这个扩展扩展的是Edible
,不是Fish
类。现在任何完成了协议Edible
的类型都能够运用eat
办法的默许完成了,例如:
class Apple: Edible {
// Do nothing…
}
let apple = Apple()
apple.eat() // Output: Eating the thing…
在上例中就能够直接调用eat()
办法了。尽管Apple
类并没有供给eat
办法的完成。
最后
扩展添加了编写代码的方法,你能够给一个你无法修正的类添加办法、核算特色。你也能够运用扩展来更好的安排代码。用着着实不错!