Swift学习( 十一:构造过程(1))

构造过程是使用类、结构体或枚举类型的实例之前的准备过程。通过定义构造器来实现构造过程。swift的构造器不需要返回值。

1.存储属性的初始赋值

类和结构体在创建实例时,必须为所有存储属性设置合适的初始值。

  • 构造器
    init(){
    //.....
    }
2.自定义构造过程
  • 构造参数

      init(frome form:Double){
              form = 23.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 mage = Color(red:1.0,green:0.7,blue:1.0)
    let hegray = Color(white:0.5)

注意:如果不通过外部参数名传旨,是没办法调用构造器的。

    let verygrrem = Color(0.0,0.5,1.0)
    //编译报错,需要外部名称
  • 不带外部名称的构造器参数
    如果不希望为构造器提供外部参数,可以使用_来描述外部名

      struct Celsius{
              var temp:Double
              init( _ clel:Double)
      }
    
      let bodytemp = Celsius(37.0)
    
3. 默认构造器

如果结构体或类的所有属性都有默认值,同时没有自定义构造器,系统则会提供一个默认构造器。默认构造器会简单的创建一个所有属性值都设置为默认值的实例

    class shop {
            var anme:String?
            var quatiy = 1
            var purh = false
    }
    var item = shop()

*结构体逐一构造器
用来初始化结构体新实例里成员属性的快捷方法。

    struct Size {
            var width = 0.0, height = 0.0
    }
    let twobytwo = Size(width:2.0,height:3.0)

类里面的所有属性(包括所有继承自父类的属性)都必须在构造过程中设置初始值。

4. 指定构造器和便利构造器

指定构造器初始化类中提供的所有属性,并根据父类链往上调用父类的构造器来实现父类的初始化。每一个来都必须拥有至少一个指定构造器。
便利构造器可以调用同一个类中的指定构造器,并为其参数提供默认值。

    指定构造器
    init(){

    }
    
    便利构造器
    convenience init(){

    }

指定构造器必须调用其直接父类的指定构造器。
便利构造器必须顶用同一类中定义的其他构造器
便利构造器必须最终导致一个指定构造器被调用。

便利构造器和指定构造器的关系
更复杂一点的关系
5.两段式构造过程

分两个阶段:第一个阶段,每个存储型属性被引入它们的类指定一个初始值。当每个存储型属性的初始值被确定后,第二阶段开始,它给每个类一次机会,在新实例准备使用之前进一步定制它们的存储型属性。
两段式构造过程的使用让构造过程更安全,同时在整个类层级结构中给予了每个类完全的灵活性。两段式构造过程可以防止属性值在初始化之前被访问,也可以防止属性被另外一个构造器意外地赋予不同的值。

    Swift 编译器将执行 4 种有效的安全检查,以确保两段式构造过程能不出错地完成:
    1.指定构造器必须保证它所在类引入的所有属性都必须先初始化完成,之后才能将其它构造任务向上代理给父类中的构造器。

    如上所述,一个对象的内存只有在其所有存储型属性确定之后才能完全初始化。为了满足这一规则,指定构造器必须保证它所在类引入的属性在它往上代理之前先完成初始化。

    2.指定构造器必须先向上代理调用父类构造器,然后再为继承的属性设置新值。如果没这么做,指定构造器赋予的新值将被父类中的构造器所覆盖。

    3.便利构造器必须先代理调用同一类中的其它构造器,然后再为任意属性赋新值。如果没这么做,便利构造器赋予的新值将被同一类中其它指定构造器所覆盖。

    4.构造器在第一阶段构造完成之前,不能调用任何实例方法,不能读取任何实例属性的值,不能引用self作为一个值。

    类实例在第一阶段结束以前并不是完全有效的。只有第一阶段完成后,该实例才会成为有效实例,才能访问属性和调用方法。

以下是两段式构造过程中基于上述安全检查的构造流程展示:

阶段 1
  • 某个指定构造器或便利构造器被调用。
  • 完成新实例内存的分配,但此时内存还没有被初始化。
  • 指定构造器确保其所在类引入的所有存储型属性都已赋初值。存储型属性所属的内存完成初始化。
  • 指定构造器将调用父类的构造器,完成父类属性的初始化。
  • 这个调用父类构造器的过程沿着构造器链一直往上执行,直到到达构造器链的最顶部。
  • 当到达了构造器链最顶部,且已确保所有实例包含的存储型属性都已经赋值,这个实例的内存被认为已经完全初始化。此时阶段 1 完成。
阶段 2
  • 从顶部构造器链一直往下,每个构造器链中类的指定构造器都有机会进一步定制实例。构造器此时可以访问self、修改它的属性并调用实例方法等等。
  • 最终,任意构造器链中的便利构造器可以有机会定制实例和使用self。
6.构造器的继承和重写
  • swift默认情况下不会继承父类的构造器。
    重写父类构造器的指定构造器时,必须在定义子类构造器时带上override修饰符。* override修饰符会让编译器去检查父类中是否有相匹配的指定构造器,并验证构造器参数是否正确。
  • 如果编写了一个和父类便利构造器相匹配的子类构造器,而子类构造器不能直接调用父类的便利构造器,所以,在重写父类便利构造器时,不用加override
7.构造器的自动继承
  • 如果子类没有定义任何指定构造器,它将自动继承所有父类的指定构造器。
  • 如果子类提供了所有父类指定构造器的实现——无论是通过规则 1 继承过来的,还是提供了自定义实现——它将自动继承所有父类的便利构造器。

注意:子类可以将父类的指定构造器实现为便利构造器。

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

推荐阅读更多精彩内容

  • 本章将会介绍 存储属性的初始赋值自定义构造过程默认构造器值类型的构造器代理类的继承和构造过程可失败构造器必要构造器...
    寒桥阅读 765评论 0 0
  • 构造过程是使用类、结构体或枚举类型的实例之前的准备过程。在新实例可用前必须执行这个过程,具体操作包括设置实例中每个...
    莽原奔马668阅读 675评论 0 3
  • 官方文档 初始化 Initialization是为准备使用类,结构体或者枚举实例的一个过程。这个过程涉及了在实例里...
    hrscy阅读 1,131评论 0 1
  • 在感情里,一开始做猎物的好处是可以选择逃离。但如果一开始就做了猎人,就要背负许多劳累。 钱迦桐作为...
    矔疏阅读 92评论 0 0
  • (一) 尹兄博学才艺多,严谨沉稳高品德。 军队地方屡建树,不好烟酒爱工作。 (二) 宣传军人价值观,登顶战区才华展...
    小车16阅读 134评论 3 0