Swift3.0学习笔记-Initialization

https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID203


You implement this initialization process by defining initializers, which are like special methods that can be called to create a new instance of a particular type. Unlike Objective-C initializers, Swift initializers do not return a value. Their primary role is to ensure that new instances of a type are correctly initialized before they are used for the first time.

          Swift类、结构体、枚举都支持构造函数, 跟其Java/C++/OC一样在构造函数中设置成员属性的初值。Swift支持多个构造函数,使用不同参数类型区分; 构造函数没有返回值初始化过程可以执行失败(并非内存不足,可以是逻辑原因;对比Java只在内存不足时实例化失败)。

        前几篇博文已经写了很多类了, 如果没写构造函数,Swift会使用默认的构造函数初始化、成员变量都是对应类型的默认值(跟Java一样)。

        Swift的构造函数并非使用类名, 而是使用init关键字。

  • init(parameters) {
  •     statements
  • }

struct Color {
    let red, green, blue: Double
    init(red: Double, green: Double, blue: Double) {
        self.red = red   //类成员变量和局部变量同名时使用self区分
        self.green = green
        self.blue = blue
    }
    init(white: Double) {
        red = white
        blue = white
        green = white
    }
}
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
let halfGray = Color(white: 0.5)
上面是init构造函数的用法, 可以有多个init函数,在调用时使用类名、括号和参数。


对于可选类型(Optional Type)包括Int? , String?, Double?, 默认值都是nil。

class Question {
    var text: String?     //默认值nil
    var level: Int?       //默认值nil
    func showText() {
        guard text != nil else {
            print("text is \(text), values is \(level)")
            return
        }
        print("text is \(text!), value is \(level!)") //注意变量后面跟个叹号,是可选参数类型取值
        
    }
    init(_ param: String, _ level: Int) {
        print("Question construct2")
        text = param
        self.level = level
    }
    init() {
        print("Question construct1")
    }
}
var question1 = Question()  //Question construct1
question1.showText()   //text is nil, values is nil
var question2 = Question("what", 1) //Question construct2
question2.showText()   //text is what, value is 1
输出:

Question construct1

text is nil, values is nil

Question construct2

text is what, value is 1


类成员常量声明方法:1、直接赋值;2、构造函数里赋值。  使用构造函数必须在所有的构造函数里赋值, 如果只赋一个值建议用直接赋值的方式; 如果可以赋多个值,那么建议用构造函数赋值的方式。 

 PS: 这个语法跟Java不同, Java在声明常量时必须赋值; 而Swift可以在构造函数里给常量赋值。

class Question {
    let constantValue: String
    let constantValueExt = "constantExt"
    ...
    convenience init(_ param: String, _ level: Int) {
        self.init()   //调用其它构造函数, 必须加前缀self
        print("Question construct2")
        text = param
        self.level = level
    }
    init() {
        print("Question construct1")
        constantValue = "constant1"   //可以修改常量!
    }
}

跟Java语言一样, 构造函数可以调用同类、结构体、枚举的其它构造函数, 但必须要添加self前缀。


便利构造函数convenience init, 可以调用同级其它init函数; init函数不能直接调用其它init函数; Xcode会给出提示。

initializerDelegation02_2x.png



类的初始化过程分为2步, 第一步初始化成员变量, 第二步执行构造函数。(跟Java的执行时序一致)


构造函数可能返回nil,即实例化函数不一定成功, 语法是init? 。

class A {
    var value: Int
    init() {
        value = 0
        print("A init value = 0")
    }
    init(value: Int) {
        self.value = value
        print("A init with value \(value)")
    }
}

class B: A {
    var param: Int
    var property: String
    override init() {
        param = 0
        property = "zhangsan"
        super.init()    //调用基类A的init构造函数
        print("B init")
    }
    init(_ value: Int) {
        param = 0
        property = "lisi"
        super.init()   //调用基类的构造函数
        print("B init with \(value)")
    }
    init?(_ param: String?) {
        guard param != nil else {
            return nil
        }
        self.param = 2
        self.property = param!
        super.init()
    }
}
var b = B(1)

A init value = 0

B init with 1

如上面代码所示, 构造函数可能返回nil时, 使用init?。 Swift还提供了init!语法代替init?,二者作用是一样的,都能返回nil。 注意派生类的init函数必须要调用基类的init函数!否则Xcode会提示错误。


Swift还提供关键字required init作为一种构造函数, 所有派生类必须覆盖该构造函数。

class A {
    var value: Int
    required init() {
        value = 0
        print("A init value = 0")
    }
    ...
}

class B: A {
    ...
    required init() {  //覆盖基类的构造函数不用写override关键字, 只用required就行了
        param = 0
        property = "zhangsan"
        super.init()    //调用基类A的init构造函数
        print("B init")
    }
    ...
}

Swift的构造函数有一些特点:

1、使用init作为构造函数, 支持重载;

2、构造函数init?或者init!可以返还nil; 

3、调用同级其它init函数时,要声明为convenience init函数;

4、派生类的init函数可以调用基类的nit函数,但必须在给所有成员属性赋值之后;

5、init函数可以继承,但convenience init不能继承;

6、当基类的构造函数声明为required init时,所有派生类必须覆盖该函数;





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值