swift学习笔记->初始化

这节重点讲下swift的初始化函数   也就是构造函数init

类,结构,枚举  都有初始化函数,就拿类举例  

首先说明一点   在类的初始化时  所有储存属性必须有值   这点在前面类的学习中也有提到过

class test{
  var i:Int  
}

所以说这样是会报错的  

初始化方法  构造器

class test{
  var i:Int = 1  
}//此时该类拥有一个默认的初始化方法   方法中给变量ii赋值
class test1{
  var i:Int 
  init (){
    self.i=1
   }    
} //此时test1自定义了一个构造器   也就是初始化方法

 特定构造器与便利构造器

特定(专门)的初始化器  designated initliazer

作用:给当前类所有储存属性赋值

注意:

  1.特定构造器可以有多个

  2.特定构造器不能相互调用(建议一个类只写一个特定构造函数)

便利构造(函数)器  convenience init 

1.可以实现许多便利的构造方式,类似于java多个构造函数 

2.便利构造函数遵循原则:必须调用特定构造函数(直接或间接) 

3.swift根据构造函数的形参名字区分构造函数而不是参数个数比如可以定义两个便利构造函数

convenience init(a:Int){

代码块

调用特定构造

}

 

convenience init(b:Int){

 

代码块

 

调用特定构造

 

}

他们不存在冲突   这是与其他语言不同的   下面看几个例子

class AA {
    var m:Int
    var n:Int
    init(mm: Int,nn: Int) {
        m = mm
        n = nn
    }
    init() {
        m = 111
        n = 22
        //这里会报错,表明特定的init之间不能相互调用
        // self.init(mm:111,nn:222)
    }
    
    //便利的初始化器需要调用专门的初始化器(直接或间接都可以)
    convenience init(mm: Int){
        self.init(mm:mm,nn:1)
    }
    
    convenience init(nn: Int){
        self.init(mm:nn)
    }
    
}

什么时候用到便利构造呢?

class test{
    var a:Int
    var b:Int
    var c:Int
    init(a:Int,b:Int,c:Int){
        self.a=a
        self.b=b
        self.c=c
    }
    convenience init(a:Int){
        self.init(a:a,b:0,c:0)
    }//初始化时只给a赋值
    convenience init(b:Int){
        self.init(a:0,b:b,c:0)
    }//初始化时只给b赋值
    convenience init(c:Int){
        self.init(a:0,b:0,c:c)
    }//初始化时只给b赋值
    convenience init(a:Int,b:Int){
        self.init(a:a,b:b,c:0)
    }//初始化时赋值a与b
    convenience init(b:Int,c:Int){
        self.init(a:0,b:b,c:c)
    }//初始化时赋值b与c
}

这样他就有许多方便使用的实例化方式了(根据需求去写  不用太多)

构造基本上就是这样    那么如果类被继承呢?

构造函数会不会被继承?

答案是会的(默认情况下会继承父类特定的构造函数)  便利构造函数也能不过要满足条件

1.子类把父类所有特定构造函数都实现(也就是重写)

2.当前类的存储属性必须声明时赋值或重写时先赋值在重写父类特定构造

下面看两个例子

 

class P{
    var m: Int
    init(m: Int) {
        self.m = m
    }
    init(m: Int,f: Bool) {
        self.m = m
    }
    convenience init() {
        self.init(m: 1)
    }
    
}
class C: P{
    var n: Int = 1
    override init(m: Int) {
        super.init(m: m)
    }
    override init(m: Int, f: Bool) {
        super.init(m: m, f: f)
    }//重写父类两个特定构造将会继承父类的便利构造
    
    //    init(n: Int) {
    //        self.n = n
    //        super.init(m: 1)
    //    }
}
var aa = C()         //父类便利构造
var bb = C(m: 2)  //被重写的特定构造
var cc = C(m: 2, f: true)//被重写的特定构造
//var dd = C(n: 2)//子类自身特定构造

当子类的属性声明时没有赋值的情况

子类构造方法必须先给子类属性赋值  在调用父类特定构造方法(不能调用父类便利构造方法)

 

class P{
    var m: Int
    init(m: Int) {
        self.m = m
    }
    init(m: Int,f: Bool) {
        self.m = m
    }
    convenience init() {
        self.init(m: 1)
    }
    
}
class C: P{
    var n: Int
    override init(m: Int) {
        self.n = 1
        super.init(m: m)
    }//重写父类特定构造
    override init(m: Int, f: Bool) {
        self.n = 1
        super.init(m: m, f: f)
    }//重写父类特定构造
    
        init(n: Int) {
            self.n = n
            super.init(m: 1)
        }//自己的特定构造
}
var aa = C()
var bb = C(m: 2)
var cc = C(m: 2, f: true)
var dd = C(n: 2)//继承了父类的特定构造

 

 

 

可失败的初始化

这种情况并不多见  举个例子

class FailureClass {
    var name:String
    init?(name:String) {
        
        self.name = name
        if name.isEmpty { return nil}
        
        
    }
}
//返回的是一个可为nil的类型
let ins = FailureClass(name: "aa")
ins?.name
if let xx = ins {
    xx.name
}
ins!.name

一般来说赋值失败不可能出现   如果失败则实例化返回nil值

加了?问号的初始化构造方法返回的是一个可选对象 访问时也需要解封   这个参考前面 可选的与可选链

 

posted @ 2015-11-18 20:19  孤独De灵魂  阅读(240)  评论(0编辑  收藏  举报