swift正确的init姿势

源于一个segmentFault提问,为什么在init方法里,self.xxx可以在super.init()之前,而print(self)不可以。

期初猜想是self的内存分配和super的是分离的,self.xxx可以是因为这个xxx是当前类的属性,而print(self)实际会访问self所有的内存,也就包括super的部分,而这时super是没有初始化的。

然后找文档验证,虽然没有很吻合,但找到了init方法的一些原则,也算是相关。主要没有说内存方面为什么这么干,只是说swift规定了就是这么干。

文档在InitializationTwo-Phase Initialization部分。把主要的部分说一下。

  • 啥叫 Two-Phase Initialization

Class initialization in Swift is a two-phase process. In the first phase, each stored property is assigned an initial value by the class that introduced it. Once the initial state for every stored property has been determined, the second phase begins, and each class is given the opportunity to customize its stored properties further before the new instance is considered ready for use.

就是初始化分两个阶段,第一个阶段,把每一个stored property赋值,然后customize its stored properties,说实话这个我不知道具体是干啥,猜测是优化一下各个属性的内存分配之类的。关键不是这个,关键是最后的 before the new instance is considered ready for use.也就是这个对象被使用之前,必须先做好第一阶段的赋值工作。

然后是4个检测:

  • 第一个

A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.

简单说,调用super.init()之前必须把所有(存储)属性赋值好,这里没有提stored词修饰,实际计算属性是不用管这些的(尼玛计算属性连初始值都不需要,还管这个)。

这一条就对应了问题里的self.xxx可以在super.init()之前调用,其实不是可以而是必须!当然赋值还有其他渠道:

  1. 本身是optional类型,默认值就是nil,那不需要再赋值了。
  2. var name = "123",在声明属性时就给了默认值了,也不需要在init里搞了。

那为啥super.init()之后也可以self.xxx = xxx赋值呢?这时已经初始化结束了,就跟在其他函数里使用了一样,其实已经不属于Initialization的行为范畴了。

  • 第二个

A designated initializer must delegate up to a superclass initializer before assigning a value to an inherited property. If it doesn’t, the new value the designated initializer assigns will be overwritten by the superclass as part of its own initialization.

必须先调用super.init(),然后才可以对继承过来的属性赋值,举例:

class test1 {
    var name:String?
    init() {
        name = "1"
        print(self);
    }
}

class test2: test1 {
    override init() {
        self.name = "234"  //这里报错
        super.init()

    }
}

注意这时候name是optional了,也会报错,跟第一点稍有不同。

  • 第三点

A convenience initializer must delegate to another initializer before assigning a value to any property (including properties defined by the same class). If it doesn’t, the new value the convenience initializer assigns will be overwritten by its own class’s designated initializer.

init方法分designated initializer和convenience initializer,后者要先调用同一个类里面的前者,在调用之后才能给自身或父类的属性赋值。举例:

convenience init(name:String, age:Int){
      self.age = 10  //这里报错
      self.init()
  }
  • 第四点

An initializer cannot call any instance methods, read the values of any instance properties, or refer to self as a value until after the first phase of initialization is complete.

在init方法里,不能调用实例方法、读取对象属性值页不能把self当做值来使用,比如print(self),除非第一阶段已经完成。

第一阶段上面已经说了,更具体的文档里有,简单说下过程:调用init方法 --> 分配当前类的内存 --> 确认所有存储变量赋值 -->调用super.init(),沿着继承链向上,保证所有父类都完成“存储变量赋值”这一步,至此第一阶段完成。

总结下,就是当前类和它所有父类的存储变量都被分配好,然后你才能使用新建的这个对象。

所以这就是为啥print(self)在super.init()之前调用会报错。

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

推荐阅读更多精彩内容