学习Swift -- 拓展

Posted Alex_sun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习Swift -- 拓展相关的知识,希望对你有一定的参考价值。

拓展(Extension)

扩展就是向一个已有的类、结构体、枚举类型或者协议类型添加新功能。这包括在没有权限获取原始源代码的情况下扩展类型的能力(即逆向建模)。扩展和 Objective-C 中的分类(categories)类似。(不过与 Objective-C 不同的是,Swift 的扩展没有名字。

Swift的拓展可以:

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

注意:扩展可以对一个类型添加新的功能,但是不能重写已有的功能。

基本语法:

class SomeClass {

}

extension SomeClass {
    // 在这里可以添加SomeClass的新功能
}

 一个扩展可以扩展一个已有类型,使其能够适配一个或多个协议。当这种情况发生时,协议的名字应该完全按照类或结构体的名字的方式进行书写:

protocol SomeProtocol {
    
}

class SomeClass {

}

extension SomeClass : SomeProtocol {
    
}

 

计算型属性

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

注意:扩展可以添加新的计算属性,但是不可以添加存储属性,也不可以向已有属性添加属性观测器

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 oneInch = 25.4.mm
print(oneInch)
// 0.0254

let threeFeet = 3.0.ft
print(threeFeet)
// 0.914399970739201

let aMarathon = 42.0.km + 195.0.m
print(aMarathon)
// 42195

 

构造器

扩展可以向已有类型添加新的构造器。这可以让你扩展其它类型,将你自己的定制类型作为构造器参数,或者提供该类型的原始实现中没有包含的额外初始化选项。 

扩展能向类中添加新的便利构造器,但是它们不能向类中添加新的指定构造器或析构器。指定构造器和析构器必须总是由原始的类实现来提供。

注意:如果你使用扩展向一个值类型添加一个构造器,在该值类型已经向所有的存储属性提供默认值,而且没有定义任何定制构造器时,你可以在值类型的扩展构造器中调用默认构造器和逐一成员构造器。正如在值类型的构造器代理中描述的,如果你已经把构造器写成值类型原始实现的一部分,上述规则不再适用。

struct Size {
    var width = 0.0, height = 0.0
}

struct Point {
    var x = 0.0, y = 0.0
}

struct Rect {
    // Rect结构体为所有属性提供了默认值,而且也没有自定义构造器,这样可以在拓展中调用Rect的逐一构造器和默认构造器
    var origin = Point(), size = Size()
}

extension Rect {
    // 在拓展中自定义了构造器
    init(center: Point, size: Size) {
        let x = center.x - size.width / 2
        let y = center.y - size.height / 2
        self.init(origin: Point(x: x, y: y), size: size)
    }
}

let rect = Rect(center: Point(x: 50, y: 50), size: Size(width: 25, height: 30))

 

方法

扩展可以向已有类型添加新的实例方法类型方法

extension Int {
    func repetitions(task: () -> ()) {
        for _ in 0 ..< self {
            task()
        }
    }
}

3.repetitions { 
    print("hello")  // 打印3次  "hello"
}

 

修改实例方法

通过扩展添加的实例方法也可以修改该实例本身结构体和枚举类型中修改self或其属性的方法必须将该实例方法标注为mutating,正如来自原始实现的修改方法一样。

extension Int {
    // 定义了值类型修改实例的方法
    mutating func square() {
        self = self * self
    }
}

var number = 3
number.square()     // number 现在的值是 9

 

下标

扩展可以向一个已有类型添加新下标

extension Int {
    subscript (var index: Int) -> Int {
        var decimalBase = 1
        while index > 0 {
            decimalBase *= 10
            index -= 1
        }
        return self / decimalBase % 10
    }
}

15699632[2]     // return 6
15699632[3]     // return 9
15699632[4]     // return 9
15699632[5]     // return 6
15699632[6]     // return 5

 

嵌套类型

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

extension Int {
    enum Kind {
        case Negative, Zero, Positive
    }
    
    var kind: Kind {
        switch self {
        case 0:
            return .Zero
        case let number where number > 0 :
            return .Positive
        default:
            return .Negative
        }
    }
}

func printIntegerKinds(numbers: [Int]) {
    for number in numbers {
        switch number.kind {
        case .Negative:
            print(" - ")
        case .Zero:
            print(" 0 ")
        default:
            print(" + ")
        }
    }
}

printIntegerKinds([0, 11, -4, 5, 0])

 

以上是关于学习Swift -- 拓展的主要内容,如果未能解决你的问题,请参考以下文章

Swift学习(4懒加载计算型属性反射机制)

Swift学习:扩展(Extensions)

Swift get和set方法以及只读属性(计算型属性,本身不保存数据,都是通过计算获得结果)

关于swift中的只读属性

Swift学习第四枪

swift 3.0 协议笔记