Swift 初始化方法

初始化方法顺序

与 Objective-C 不同,Swift 的初始化方法需要保证类型的所有属性都被初始化。所以初始化方法的调用顺序就很有讲究。在某个类的子类中,初始化方法里语句的顺序并不是随意的,我们需要保证在当前子类实例的成员初始化完成后才能调用父类的初始化方法。

class Cat {
    var name: String
    init() {
        name = "cat"
    }
}

class Tiger: Cat {
    let power: Int
    override init() {
        power = 10
        super.init()
        name = "tiger"
    }
}

一般来说,子类的初始化顺序是:

  1. 设置子类自己需要初始化的参数,power = 10
  2. 调用父类的相应的初始化方法,super.init()
  3. 对父类中的需要改变的成员进行设定,name = "tiger"

如果在子类中不需要对父类的成员做出改变的话就不存在第 3 步。这种情况下,第2步的super.init()也不需要手动调用了,Swift可以自动的帮我们完成。于是上面的代码可以改成如下的形式:

class Cat {
    var name: String
    init() {
        name = "cat"
    }
}

class Tiger: Cat {
    let power: Int
    override init() {
        power = 10
        // 如果我们不需要改变 name 的话,
        // 虽然我们没有显式地对 super.init() 进行调用
        // 不过由于这是初始化的最后了,Swift 替我们自动完成了
    }
}

DESIGNATED,CONVENIENCE 和 REQUIRED

在Objective-C中,init方法是非常不安全的,因为没有人能保证init方法只被调用一次,也没有人保证在初始化方法调用以后实例的各个变量都完成初始化,甚至如果在初始化里使用属性进行设置的话,还可能会造成各种问题
所以 Swift 有了超级严格的初始化方法。一方面,Swift 强化了 designated 初始化方法的地位。Swift 中不加修饰的 init 方法都需要在方法中保证所有非 Optional 的实例变量被赋值初始化,而在子类中也强制 (显式或者隐式地) 调用 super 版本的 designated 初始化,所以无论如何走何种路径,被初始化的对象总是可以完成完整的初始化的。

class ClassA {
    
    let numA: Int

    init(num: Int) {
        numA = num
    }

    convenience init(bigNum: Bool) {
        self.init(num: bigNum ? 1000 : 1)
    }
}

class ClassB: ClassA {
    
    let numB: Int
    
    /*
     只要在子类中实现重写了父类convenience方法所需要的init方法的话,
     我们在子类中就也可以使用父类的convenience初始化方法了。
     */
    override init(num: Int) {
        numB = num + 1
        super.init(num: num)
    }
}

let bObj = ClassB(bigNum: true)

bObj.numA // 1000
bObj.numB // 1001

从上面的代码可以看出,init方法可以对let变量进行赋值操作,这是初始化方法最重要的特点。因为 Swift 的 init 只可能被调用一次,因此在 init 中我们可以为常量进行赋值,而不会引起任何线程安全的问题。

convenience关键字修饰的init方法是用于补充和提供使用上的方便。所有的 convenience 初始化方法都必须调用同一个类中的 designated 初始化完成设置,另外 convenience 的初始化方法是不能被子类重写或者是从子类中以 super 的方式被调用的。

对于某些我们希望子类中一定实现的 designated 初始化方法,我们可以通过添加 required 关键字进行限制,强制子类对这个方法重写实现。
这样做的最大的好处是可以保证依赖于某个 designated 初始化方法的 convenience 一直可以被使用

如果我们不使用required关键字来限制的话,那么下面的ClassC这个类就无法调用父类中的init(bigNum: Bool)方法

class ClassC: ClassB {
    
    let numC: Int
    
    init(cNum value: Int) {
        numC = value
        super.init(num: 100)
    }
}

// 这里已经不能调用ClassA中的convenience初始化方法
let cObj = ClassC(cNum: 10)

cObj.numA // 100
cObj.numB // 101
cObj.numC // 10

另外需要说明的是,其实不仅仅是对 designated 初始化方法,对于 convenience 的初始化方法,我们也可以加上 required 以确保子类对其进行实现。这在要求子类不直接使用父类中的 convenience 初始化方法时会非常有帮助。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容