Swift-扩展extension

扩展就是向一个已有的类、结构体和枚举类型添加新功能。扩展可以对一个类型添加新的功能,但是不能重写已有的功能。

Swift中扩展可以:

  • 添加计算型属性和计算型静态属性
  • 定义实例方法和类型方法
  • 提供新的构造器
  • 定义下标
  • 定义和使用新的嵌套类型
  • 使一个已有类型符合某个协议

语法:扩展声明使用关键字extension

1
2
3
extension SomeType{
// 加到SomeType的新功能
}

一个扩展可以扩展一个已有尅性,使其能够适配一个或多个协议,语法格式:

1
2
3
extension SomeType: SomeProtocol, AnotherProtocol{
// 协议实现写到这里
}

计算型属性

扩展可以向已有类型添加计算型实例属性和计算型类型属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 扩展Int类型,添加属性
extension Int {
var autoAdd: Int {
return self + 2
}
var autoSub: Int {
return self - 2
}
var autoMul: Int {
return self * 2
}
var autoDiv: Int {
return self / 2
}
}

let addition = 3.autoAdd
print("加法:\(addition)") // 加法:5

let subtraction = 3.autoSub
print("减法:\(subtraction)") // 减法:1

let multiplication = 3.autoMul
print("乘法:\(multiplication)") // 乘法:6

let division = 3.autoDiv
print("除法:\(division)") // 除法:1

let mix = 3.autoDiv + 5.autoAdd
print("除法:\(mix)") // 除法:8

扩展可以添加新的计算型属性,但是不可以添加存储型属性,也不可以为已有属性添加属性观察器

构造器

  • 扩展可以向已有类型添加新的构造器。
  • 扩展可以定制类型作为构造器参数,或者提供该类型的原始实现中没有包含的额外初始化选项。
  • 扩展可以向类中添加新的便利构造器init(),但是不能向类中添加新的指定构造器或析构函数deinit()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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()
// init(origin:Point) {
// self.origin = origin
// }
}


extension Rect{
// 添加一个额外的接收指定中心点和大小的构造器来扩展Rect结构体
init(center:Point, size:Size) {
let x = center.x - (size.width / 2)
let y = center.y - (size.height / 2)
/*
因为结构体没有提供定制的构造器,因此扩展会获得一个逐一成员构造器,又因为结构体所有的存储属性提供了默认值,又会获得一个默认构造器。
所以如果Rect提供了定制构造器:
init(origin:Point) {
self.origin = center
}
那么self.init(origin: Point(x: x, y: y), size: size)就会报错
*/

self.init(origin: Point(x: x, y: y), size: size)
}
}

let centerRect = Rect(center: Point(x: 4, y: 4), size: Size(width: 3, height: 3))
print("centerRect center:\(centerRect.origin.x), \(centerRect.origin.y). size:\(centerRect.size.width), \(centerRect.size.height)")
// centerRect center:2.5, 2.5. size:3.0, 3.0

方法

扩展可以为已有类型添加实例方法和类型方法

实例方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
extension Int {
func repetition(task: () -> ()) {
for _ in 0..<self {
task()
}
}
}

3.repetition {
print("repetition 3次")
}
//repetition 3次
//repetition 3次
//repetition 3次

2.repetition {
print("repetition 2次")
}
//repetition 2次
//repetition 2次
类型方法
1
2
3
4
5
6
7
8
9
extension Int {

static func Square(_ number:Int) -> Int {
return number * number
}
}

let number = Int.Square(2)
print(number) // 4
可变实例方法

通过扩展添加的实例方法也可以修改该实例本身。结构体和枚举类型中修改self或其他属性的方法必须将该方法标注为mutating

1
2
3
4
5
6
7
8
9
10
extension Int {
mutating func square(){
self = self * self
}
}

var number = 5
print(number) // 5
number.square()
print(number) // 25

下标

扩展可以为已有类型添加新下标,该下标返回十进制数字从右到左数的第n个数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
extension Int {
subscript(index:Int) -> Int{
var value = 1
for _ in 0..<index{
value *= 10
}
return (self/value) % 10
}
}

print(44558[0]) // 8
print(44558[1]) // 5
print(44558[2]) // 5
print(44558[3]) // 4

// 如果该Int值没有足够的位数,即下标越界,那么上述下标实现会返回0,像似在数字左边自动补0:044558
print(44558[5]) // 0

嵌套类型

扩展可以为已有的类、结构体和枚举添加新的嵌套类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
extension Int{
enum Kind {
case Negative, Zero, Posttive
}

var kind:Kind {
switch self {
case 0:
return .Zero
case let x where x > 0:
return .Posttive
default:
return .Negative
}
}
}

let kingArray = [3, 0, -4, 88, 74, 0, -9]
for item in kingArray {
switch item.kind {
case .Negative:
print("\(item):负数")
case .Zero:
print("\(item):0")
case .Posttive:
print("\(item):正数")
}
}
//3:正数
//0:0
//-4:负数
//88:正数
//74:正数
//0:0
//-9:负数

参考: