Swift构造器总结(限制&注意点)【转】

原文:http://ghui.me/post/2016/05/swift-init/

Swift的构造器的编写规则要比其它语言麻烦很多, 有很多限制, 有些限制也不是那么容易想明白的, 但我想Swift的设计者肯定是有自己的考虑,不会平白无故的去设置这些限制,在这篇文章中我将试着总结一下Swift语言在构造过程中的种种限制以及为什么会需要这些限制.

1: Swift会为构造器的每个参数自动生成一个跟内部名字相同的外部名

构造器并不像函数和方法那样在括号前有一个可辨别的名字(构造器统一叫init), 为了提高构造器的可读性就有了这条限制, 当然如果你实在是不想为构造器提供外部名,可以使用下划线_来显式描述它的外部名, 这样就不会有上述默认行为了.

2: 任何一个构造器都必须使当前对象内的非lazy非Optional类型的存储属性获得确定值

如果你之前做过Java开发, 你可能会对这一点产生疑惑, 在Java的构造器里我们是不需要对所有的字段显示进行赋值的.
其实这个和Swift引入的Optional有关,在Swift中非Optional的变量默认是不会有值的, 除非你将它显示的定义为Optional的, 换句话说Swift中Optional类型的变量才相当于Java中的变量(java中的全局变量会自动被赋予默认值).而Swift中Optional类型的变量才会有默认值nil, 而且构造器的目的就是分配内存以及使当前对象处于一个确定的状态(属性都有值包括nil)

3: 如果结构体或类的所有的属性都有默认值, Swift才会为它们提供默认构造器

在java中如果你没有定义构造器, Java就会自动为你提供一个默认构造器, Swift为什么不?
基实这个和限制2的原因是一样的, 首先构造器要保证当前对象所有的属性都有值, 而Swift中的非Optionl类型的变量没有默认值, 所以只有当所有属性都有默认值的情况下Swift才能提供默认构造器.

4: 如果你自定义了构造器, 那么默认构造器会丢失(如果是结构体,还将丢失逐一成员构造器)

这种限制可以防止你为值类型增加了一个额外的且十分复杂的构造器之后,仍然有人错误的使用自动生成的构造器. 如果你想保留默认构造器逐一成员构造器以及你自己定义的构造器,你可以将自定义构造器定义到extension中

5. 指定构造器与便利构造器是针对类而言的, 值类型的构造器没有这一说

6. 指定构造器必须总是向上代理, 便利构造器必须总是横向代理

之所以要这样规定, 官方的说法是为了简化指定构造器与便利构造器之间的调用关系:
1: 指定构造器必须调用其直接父类的的指定构造器
2: 便利构造器必须调用同一类中定义的其它构造器
3: 便利构造器必须最终导致一个指定构造器被调用


7. 两段式构造过程

第一个阶段: 每个存储属性都获得一个初始值
第二个阶段: 进一步定制存储属性的值
两段式构造过程可以防止属性在初始化之前被访问, 也可以防止属性被另外一个构造器意外地赋予不同的值.
这个怎么理解呢? 若属性在初始化之前(第一阶段结束之前)被访问, 显然这种情况是没有意义的,因为这个时候属性还没有任何值, 另外一种情况若当前被访问的属性是从父类继承过来的, 如果它在初始化之前被访问,也是没有意义的, 因为它会被后面的super.init方法重新赋予初始值.

我对两段式构造过程的理解: 之所以要分两段式来构造和Swift引入Optional的概念还是分不开的, Swift中的变量默认都不是Optional的, 这些变量不像其它语言(如Java)中的那样会默认有初始值, 所以必须需要第一阶段来确定一个初始值.换个角度来看, 其它语言的构造器相当于直接是从第二个阶段开始的, 它们的第一阶段相当于是在定义属性时(这个时候系统会默认分配一个默认值, 如果你不显式的赋予它初始值). 所以其实,如果你在Swift中给你的属性在定义时就显式的赋予了初始值,或者你的属性是Optional的, 那么你在写构造器时也就没有这些限制了, 因为这个时候在init方法中你相当于是直接从第二个阶段开始的.

8. 4种安全检查

指定构造器必须保证它所在类引入的所有属性都必须先初始化完成,之后才能将其它构造任务向上代理给父类中的构造器.
指定构造器必须先向上代理调用父类构造器,然后再为继承的属性设置新值。如果没这么做,指定构造器赋予的新值将被父类中的构造器所覆盖。
便利构造器必须先代理调用同一类中的其它构造器,然后再为任意属性赋新值。如果没这么做,便利构造器赋予的新值将被同一类中其它指定构造器所覆盖。
构造器在第一阶段构造完成之前,不能调用任何实例方法,不能读取任何实例属性的值,不能引用self作为一个值。
这4项中只有第一条比较难理解一些,当初困扰了好久,后来在万能的stackoverflow上找到的答案,详情

9. Swift中的子类默认不会继承父类的构造器

Swift的这种机制可以防止一个父类的简单构造器被一个更精细的子类继承,并被错误地用来创建子类的实例。父类的构造器仅会在安全和适当的情况下被继承。

10. 你只能重写父类的指定构造器, 无法重写父类的便利构造器

为了简化构造器之间的调用关系, 便利构造器必须总是横向代理. 也就是说在便利构造器中是无法访问父类的构造器的, 也就不能完成从父类中继承下来的属性的初始化, 导致无法完成子类的完全初始化, 所以子类是不能重写父类的便利构造器的.

11. 子类不仅可以重写父类的指定构造器, 还可以将其重写为便利构造器

12. 构造器的自动继承

若子类中引入的存储属性都有缺省值, 且子类中没有定义任何构造方法. 那么子类将会自动继承父类中所有的构造方法(包括便利构造方法)
若子类只是重写了父类中的部分构造方法, 则子类不再会自动继承父类中的其他构造方法
若子类重写了父类中的所有指定构造方法, 则子类同时会自动继承父类中所有的便利构造方法
我的理解: 父类的构造器只会在安全和适当的情况下被继承, 满足上面三种条件中的任何一条, 子类去自动继承父类中的构造方法都是适当的,不会引起任何构造过程的混乱.

13. 可失败构造器的参数列表不能与其它非可失败构造器的参数列表相同

若参数列表相同, 则可以认为两个方法是同一个方法, 而一个方法不能同时是非可失败与可失败的

14. 可失败构造器,在返回nil前必须要将所有的stroed property赋值

从swift2.2开始已没有此限制

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

推荐阅读更多精彩内容