构造器(二)----指定构造器、便利构造器

  1. 云栖社区>
  2. 博客列表>
  3. 正文

构造器(二)----指定构造器、便利构造器

xinxinitblog 2016-03-01 11:47:00 浏览89 评论0

摘要: 在上一篇博客中简单介绍了构造器基础层面的知识构造器(一),下面我们深入的学习类的构造器应用。 在Swift中类一共有两种构造器: 指定构造器 便利构造器 什么是指定构造器,有什么作用? 我个人的理解为在类中没有加任何关键字的构造器称为指定构造器,作用为初始化类中所有的实例存储属性 init() { ... } 什么是便利构造器,有什么作用? 我个人理解为在类中(只能在类中,结构体和枚举里面是没有的)加上convenience关键字的构造器为便利构造器,作用为辅助性调用指定构造器进行一系列的工作。

在上一篇博客中简单介绍了构造器基础层面的知识构造器(一),下面我们深入的学习类的构造器应用。

在Swift中类一共有两种构造器:

  • 指定构造器
  • 便利构造器

什么是指定构造器,有什么作用?

我个人的理解为在类中没有加任何关键字的构造器称为指定构造器,作用为初始化类中所有的实例存储属性

init()
{
   ...
}

什么是便利构造器,有什么作用?

我个人理解为在类中(只能在类中,结构体和枚举里面是没有的)加上convenience关键字的构造器为便利构造器,作用为辅助性调用指定构造器进行一系列的工作。感觉体现了在Object-C中的代理模式

 convenience init()
 {
     ...
 //注意这里必须调用同一类的其他构造器,这里调用的可以是其他便利构造器或者是指定构造器
 }

综合的看一个励志吧,请原谅程序员的屌丝:

         class Man
    {
    var say:String
     init(say:String)
    {
    self.say=say
    }

    convenience init(Say:String)
    {
        self.init(say:Say)

    }
}
    var man1=Man(say: "我喜欢你!")
    print(man1.say)
    var man2=Man(Say: "啊,不,我不喜欢你!我爱你!")
    print(man2.say)

构造器的调用链遵守三条规则

  • 子类构造器必须调用直接父类的指定构造器
  • 便利构造器必须调用同一类中的其他构造器
  • 便利构造器调用的构造器的终点必须是指定构造器

类构造的两个阶段:

第一阶段:

  1. 程序调用子类的某个构造器

  2. 为实例分配内存, 此时实例的内存还没有被初始化

  3. 指定构造器确保子类定义的所有实例存储属性都已被赋初值

  4. 指定构造器将调用父类的构造器, 完成父类定义的实例存储属性的初始化

  5. 沿着调用父类构造器的构造器链一直往上执行, 直到到达构造器链的最顶部

第二阶段:

  1. 沿着继承树往下, 构造器此时可以修改实例属性和访问self, 甚至可以调用实例方法

  2. 最后, 构造器链中的便利构造器都有机会定制实例和使用self

Swift安全检查

  • 安全检查1:指定构造器必须先初始化当前类中定义的实例存储属性, 然后才能向上调用父类构造器

  • 安全检查2:指定构造器必须向上调用父类构造器, 然后才能对继承得到的属性赋值

  • 安全检查3:便利构造器必须先调用同一个类的其他构造器, 然后才能对属性赋值

  • 安全检查4:构造器在第一阶段完成之前, 不能调用实例方法, 不能读取实例属性

    class Person {
    
    var name: String!
    var weight: Double
    
    // 定义指定构造器
    init(name: String, weight: Double) {
        self.name = name
        self.weight = weight
    }
    
    // 定义便利构造器(使用convenience修饰)
    convenience init(n name: String, w weight: Double) {
        self.init(name: name, weight: weight)
    }
    

    }

    class Man: Person {
    
    var sex: String!
    
    init(sex: String, name: String, weight: Double) {
    // print(super.name) 不能再父类初始化之前调用父类中的属性
    super.init(name: name, weight: weight)
    super.name = "lala"
    print(self.name)
    // print(self.sex) 不能在本类中的属性没有进行初始化的时候进行调用
    // 会出现:fatal error: unexpectedly found nil while unwrapping an Optional value错误
    self.sex = sex
    print(self.sex)
    }
    
    convenience init(s sex: String, n name: String, weight: Double) {
    
    // 在调用其他构造器之前, 不能访问或修改任何实例存储属性
    // print(self.name) 错误
    // super.name = name 错误
    self.init(sex: sex, name: name, weight: weight)
    }
    }
    var man = Man(sex: "男", name: "Rinpe", weight: 62.0)
    

用云栖社区APP,舒服~

【云栖快讯】诚邀你用自己的技术能力来用心回答每一个问题,通过回答传承技术知识、经验、心得,问答专家期待你加入!  详情请点击

网友评论

xinxinitblog
文章183篇 | 关注3
关注
操作审计(ActionTrail)会记录您的云账户资源操作,提供操作记录查询,并可以将记录文... 查看详情
基于阿里聚安全的核心技术,为移动应用(APP)提供全生命周期的安全服务,其能够准确发现应用的... 查看详情
是阿里云安全专家基于阿里云多年安全最佳实践经验为云上用户提供的全方位安全技术和咨询服务,为云... 查看详情
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效... 查看详情
阿里云9.10会员日

阿里云9.10会员日