🎬 HoRain 云小助手个人主页

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

目录

⛳️ 推荐

Swift 构造过程

基本构造器

默认构造器

自定义构造器

构造器参数

内部参数名和外部参数名

可选参数

构造过程中的常量属性

值类型(结构体和枚举)的构造器代理

类的继承和构造过程

指定构造器和便利构造器

构造器的继承规则

可失败构造器

必要构造器

通过闭包或函数设置属性默认值

两段式构造过程

安全检查

反初始化(析构器)

构造过程总结要点


Swift 构造过程

Swift 中的构造过程是为类、结构体或枚举的实例做准备的过程,包括设置初始值和执行必要的准备。这个过程通过构造器init方法)来实现。

基本构造器

默认构造器

// 结构体的默认构造器
struct Point {
    var x: Double
    var y: Double
}

let origin = Point(x: 0.0, y: 0.0)  // 默认的成员构造器

// 类的默认构造器
class SimpleClass {
    var value: Int = 0  // 所有属性都有默认值
    
    // 不需要显式写 init(),Swift 会自动提供
}
let obj = SimpleClass()  // 调用默认构造器

自定义构造器

struct Celsius {
    var temperatureInCelsius: Double
    
    // 自定义构造器
    init(fromFahrenheit fahrenheit: Double) {
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
    }
    
    init(fromKelvin kelvin: Double) {
        temperatureInCelsius = kelvin - 273.15
    }
    
    // 不带参数标签的构造器
    init(_ celsius: Double) {
        temperatureInCelsius = celsius
    }
}

let boilingPoint = Celsius(fromFahrenheit: 212.0)  // 100.0
let freezingPoint = Celsius(fromKelvin: 273.15)    // 0.0
let bodyTemperature = Celsius(37.0)                // 37.0

构造器参数

内部参数名和外部参数名

struct Color {
    let red, green, blue: Double
    
    // 使用参数标签
    init(red: Double, green: Double, blue: Double) {
        self.red = red
        self.green = green
        self.blue = blue
    }
    
    // 省略参数标签
    init(_ white: Double) {
        red = white
        green = white
        blue = white
    }
}

let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
let gray = Color(0.5)  // 省略参数标签

可选参数

struct SurveyQuestion {
    var text: String
    var response: String?  // 可选类型,默认值为 nil
    
    init(text: String) {
        self.text = text
        // response 自动设为 nil,不需要初始化
    }
}

构造过程中的常量属性

class SurveyAnswer {
    let text: String  // 常量,只能在构造过程中修改
    var response: String?
    
    init(text: String) {
        self.text = text  // 只能在构造器中赋值
    }
    
    func setResponse(_ response: String) {
        self.response = response
        // self.text = "new"  // 错误!不能在构造器外修改常量属性
    }
}

值类型(结构体和枚举)的构造器代理

构造器可以调用其他构造器来完成实例的部分构造过程。

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

struct Rect {
    var origin = Point(x: 0.0, y: 0.0)
    var size = Size()
    
    // 三个自定义构造器
    init() {}  // 使用默认值
    
    init(origin: Point, size: Size) {
        self.origin = origin
        self.size = size
    }
    
    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        // 调用另一个构造器
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}

类的继承和构造过程

指定构造器和便利构造器

class Vehicle {
    var numberOfWheels = 0
    var description: String {
        return "有 \(numberOfWheels) 个轮子"
    }
    
    // 默认构造器(是指定构造器)
    init() {}
}

class Bicycle: Vehicle {
    var hasBasket = false
    
    // 指定构造器
    init(hasBasket: Bool) {
        self.hasBasket = hasBasket
        super.init()  // 必须调用父类构造器
        numberOfWheels = 2
    }
    
    // 便利构造器
    convenience init() {
        self.init(hasBasket: false)  // 必须调用同类的指定构造器
    }
}

构造器的继承规则

  1. 如果子类没有定义任何指定构造器,它会自动继承父类所有的指定构造器

  2. 如果子类实现了父类所有指定构造器(无论是通过继承还是自定义),它会自动继承父类所有的便利构造器

class Food {
    var name: String
    
    // 指定构造器
    init(name: String) {
        self.name = name
    }
    
    // 便利构造器
    convenience init() {
        self.init(name: "[未命名]")
    }
}

class RecipeIngredient: Food {
    var quantity: Int
    
    // 指定构造器
    init(name: String, quantity: Int) {
        self.quantity = quantity
        super.init(name: name)
    }
    
    // 重写父类指定构造器
    override convenience init(name: String) {
        self.init(name: name, quantity: 1)
    }
    // 自动继承父类的 convenience init()
}

let oneMysteryItem = RecipeIngredient()  // 继承的便利构造器
let oneBacon = RecipeIngredient(name: "培根")  // quantity = 1
let sixEggs = RecipeIngredient(name: "鸡蛋", quantity: 6)

可失败构造器

struct Animal {
    let species: String
    
    // 可失败构造器
    init?(species: String) {
        if species.isEmpty {
            return nil
        }
        self.species = species
    }
}

let someCreature = Animal(species: "长颈鹿")  // Animal?
let anonymousCreature = Animal(species: "")  // nil

// 枚举的可失败构造器
enum TemperatureUnit {
    case kelvin, celsius, fahrenheit
    
    init?(symbol: Character) {
        switch symbol {
        case "K":
            self = .kelvin
        case "C":
            self = .celsius
        case "F":
            self = .fahrenheit
        default:
            return nil
        }
    }
}

必要构造器

class SomeClass {
    // 子类必须实现此构造器
    required init() {
        // 构造器实现
    }
}

class SomeSubclass: SomeClass {
    // 必须添加 required
    required init() {
        // 构造器实现
    }
}

通过闭包或函数设置属性默认值

struct Chessboard {
    // 使用闭包设置默认值
    let boardColors: [Bool] = {
        var temporaryBoard: [Bool] = []
        var isBlack = false
        
        for _ in 1...8 {
            for _ in 1...8 {
                temporaryBoard.append(isBlack)
                isBlack = !isBlack
            }
            isBlack = !isBlack
        }
        return temporaryBoard
    }()  // 立即执行闭包
    
    func squareIsBlackAt(row: Int, column: Int) -> Bool {
        return boardColors[(row * 8) + column]
    }
}

两段式构造过程

Swift 中类的构造过程包含两个阶段:

  1. 第一阶段:为类引入的所有存储属性设置初始值

  2. 第二阶段:给每个类一次机会,在新实例准备使用之前进一步定制存储属性

安全检查

  1. 在调用父类构造器之前,必须完成本类所有存储属性的初始化

  2. 必须调用父类构造器之后,才能修改继承的属性

  3. 便利构造器必须先调用同类其他构造器,然后才能修改任何属性

  4. 在第一阶段完成之前,不能调用任何实例方法,不能读取任何实例属性,不能引用 self

class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        // 第一阶段:初始化所有存储属性
        self.name = name
        self.age = age
        
        // 第二阶段:可以调用方法
        introduceYourself()
    }
    
    func introduceYourself() {
        print("我叫 \(name),今年 \(age) 岁")
    }
}

反初始化(析构器)

class Bank {
    static var coinsInBank = 10_000
    
    static func distribute(coins numberOfCoinsRequested: Int) -> Int {
        let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank)
        coinsInBank -= numberOfCoinsToVend
        return numberOfCoinsToVend
    }
    
    static func receive(coins: Int) {
        coinsInBank += coins
    }
}

class Player {
    var coinsInPurse: Int
    
    init(coins: Int) {
        coinsInPurse = Bank.distribute(coins: coins)
    }
    
    func win(coins: Int) {
        coinsInPurse += Bank.distribute(coins: coins)
    }
    
    // 析构器
    deinit {
        Bank.receive(coins: coinsInPurse)
    }
}

构造过程总结要点

  1. 构造器的主要任务是确保实例在使用前完成正确的初始化

  2. 在构造器中,必须为所有存储属性(可选类型除外)设置初始值

  3. 值类型(结构体、枚举)支持构造器代理

  4. 类有指定构造器和便利构造器,遵循特定的调用规则

  5. 可失败构造器允许在某些条件下构造失败返回 nil

  6. 通过两段式构造过程确保安全初始化

  7. 使用 deinit在实例销毁前执行清理工作

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐