zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

Swift 中 extension 的使用

2023-04-18 15:37:49 时间

在 Swift 中,extension 是一种非常有用的语言特性,它可以为一个已有的类型(包括类、结构体和枚举)添加新的属性、方法、下标和协议等功能,而无需修改原始类型的定义。使用 extension 可以让我们更加方便地扩展和修改现有的代码,同时也可以使代码更加清晰和易读。

下面是一些 extension 的使用示例:

1. 为类型添加新的方法

extension Int {
    func times(_ closure: () -> Void) {
        for _ in 0..<self {
            closure()
        }
    }
}

3.times { print("Hello") } // 输出三次 "Hello"

在上面的代码中,我们为 Int 类型添加了一个名为 times 的方法,这个方法接受一个闭包作为参数,并在闭包中执行指定次数的操作。在调用时,我们可以使用 3.times { print("Hello") } 的语法来输出三次 "Hello"。

2. 为类型添加新的计算属性

extension Double {
    var squared: Double {
        return self * self
    }
}

let x = 3.0
let y = x.squared // y 的值为 9.0

在上面的代码中,我们为 Double 类型添加了一个名为 squared 的计算属性,这个属性返回当前值的平方。在调用时,我们可以使用 x.squared 的语法来计算 x 的平方并将结果赋值给 y

3. 为类型添加新的下标

extension Array {
    subscript(safe index: Int) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

let array = [1, 2, 3]
let element = array[safe: 10] // element 的值为 nil

在上面的代码中,我们为 Array 类型添加了一个名为 safe 的下标,这个下标接受一个整数作为参数,并返回数组中对应索引位置的元素(如果该索引位置存在的话),否则返回 nil。在调用时,我们可以使用 array[safe: 10] 的语法来获取数组中索引为 10 的元素,由于该索引位置不存在,因此返回值为 nil

4. 为类型遵循新的协议

protocol Runnable {
    func run()
}

extension UIViewController: Runnable {
    func run() {
        print("ViewController is running")
    }
}

let viewController = UIViewController()
viewController.run() // 输出 "ViewController is running"

在上面的代码中,我们为 UIViewController 类型遵循了一个名为 Runnable 的协议,并为该类型添加了一个 run 方法。在调用时,我们可以使用 viewController.run() 的语法来执行 ViewController 中的 run 方法,并输出 "ViewController is running"。

总之,extension 是一种非常有用的语言特性,可以让我们更加灵活地扩展和修改现有的代码,从而提高开发效率和代码质量。

问题:你能通过extension(扩展)保存一个属性吗?请解释一下原因。

在 Swift 中,我们可以使用 extension 来为一个已有的类型添加新的属性和方法。但是,我们不能使用 extension 来添加存储属性,因为存储属性必须在类型的定义中进行声明。

因为 extension 是在类型的定义之外添加新的功能,它只能添加计算属性,也就是只有 getter 和 setter 方法的属性,而没有实际的存储空间来存储属性值。因此,如果我们在 extension 中尝试添加一个存储属性,编译器会提示错误。

下面是一个示例代码:

struct Person {
    var name: String
}

extension Person {
    var age: Int // 编译错误:Extensions must not contain stored properties
}

在上面的代码中,我们尝试在 Person 结构体的 extension 中添加一个 age 属性,但是编译器会提示错误,因为我们不能在 extension 中添加存储属性。

不过,我们可以在 extension 中添加计算属性,这些属性会在每次访问时计算出一个值,如下所示:

extension Person {
    var fullName: String {
        return "(name)"
    }
}

在上面的代码中,我们在 Person 结构体的 extension 中添加了一个 fullName 计算属性,这个属性只有 getter 方法,每次访问时都会计算出一个完整的姓名并返回。