Swift学习笔记15——初始化(Initialization)和析构(Deinitialization)其二

这篇博客介绍了Swift中的可失败构造器(Failable Initializers),这种构造器允许在创建实例时返回nil。文中详细阐述了如何定义和使用可失败构造器,以及值类型在使用时的规则。此外,还提到了必须构造器(Required Initializers),要求子类必须重写。最后,讲解了析构器(Deinitialization)的概念,它是系统自动调用的用于清理和保存数据的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可失败的构造器(Failable Initializers

Swift中有个概念,就是创建实例的时候如果条件不符合,可以返回一个nil对象。这类可以返回nil的构造器叫做可失败的构造器。语法是在init的前面加上一个?。当条件不满足的时候,你可以用 return nil结束构造方法。那么这时候得到的实例其实是一个nil,这里也说明了,可失败构造器返回的是可选类型。其实之前也说过,Swift的构造器是不需要返回值的。所以你成功的时候不需要写return什么东东。

值类型的可失败构造器

下面是structure的。

struct Apple {
    var pricePerKg: Double
    init?(pricePerKg: Double){
        if pricePerKg < 0 {
            return nil
        }
        self.pricePerKg = pricePerKg
    }
}
print(Apple(pricePerKg: 2))
print(Apple(pricePerKg: -2))
//打印
//Optional(SwiftTest.Apple(pricePerKg: 2.0))
//nil


接下来是枚举类的,

enum FruitSet {
    case apple, orange, banana
    init?(symbol: Character){
        switch symbol {
        case "a","A" :
            self = .apple
        case "o","O" :
            self = .orange
        case "b","B" :
            self = .banana
        default :
            return nil
        }
    }
}

print(FruitSet(symbol: "a"))
print(FruitSet(symbol: "e"))
//打印
//Optional(SwiftTest.FruitSet.apple)
//nil


对应有默认值的枚举类,会自动生成一个init?(rawValue:)的构造器。如下

enum FruitSet : Character{
    case apple = "a", orange = "o", banana = "b"
}

print(FruitSet(rawValue: "a"))
print(FruitSet(rawValue: "e"))



类的可失败构造器

有一个规则,就是必须在本类所有的属性(包括继承的)都赋值之后才可以返回nil

class Apple {
    var pricePerKg: Double
    init?(pricePerKg: Double){
        if pricePerKg < 0 {
            return nil              //这句报错,所以你必须先初始化其他属性值
        }
        self.pricePerKg = pricePerKg
    }
}


可失败初始化的传递过程

一个可失败的构造器可以调用其他的构造器,无论是可失败的还是不会失败的。

但是一个不可失败的构造器不能去调用一个可失败的构造器。如果去调用父类的可失败构造器,虽然用解包可以解决,但是一旦父类的可失败构造器返回了nil,那么程序直接崩溃。

class Fruit {
    var name: String
    init?(name: String){
        self.name = name
        if name.isEmpty {
            return nil
        }
    }
}

class Apple: Fruit {
    var pricePerKg: Double
    init(pricePerKg: Double){
        self.pricePerKg = pricePerKg
        super.init(name: "")!   //利用解包调用了父类的可失败构造器,但是因为这样父类会返回一个nil,所以程序在这行会崩溃

    }
    convenience init?(){
        self.init(pricePerKg: 3)
    }
}

var i = Apple(pricePerKg: 3)


同样的,可失败的构造器也可以被重写,你可以重写为不可失败的构造器。

但是不可失败的构造器不能覆盖为可失败的构造器。


你可以用!代替?来实现可失败构造器,那么这样得到的实例会自动解包。当然,存在nil报错的问题。记得处理。


必须构造器(Required Initializers

在构造器前面加上required关键字就行了。这样的构造器要求子类必须重写。子类重写这个构造器的时候,也必须加上required关键字。要求子类的子类也要重写这个构造器。

写了required后不用写override关键字。写了会有警告。



给属性默认值时使用闭包或函数

func getprice()->Double {
    return 1
}
class Apple {
    var pricePerKg: Double = getprice()
    var name = {
        return "apple"
    }()     //留意这对小括号,没有的话那就是给属性赋值一个闭包了。
}
var a = Apple()
print(a.pricePerKg,a.name)


析构器

析构器,就是在一个实例再也不用到时候调用的方法。析构器里面完成一些清理工作或保存数据等等。析构器是系统自动调用的,不允许自行调用。

语法

deinit {
    // perform the deinitialization
}


那么什么时候才是一个实例再也不需要?这个将在下篇文章自动引用计数(ARC)里面讲。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值