Swift基础05

Swift基础05

构造器(构造函数)

类的构造过程

  • 类的构造过程就是给我们的类分配内存空间,对我们的类的存储属性赋值,生成我们想要的对象的过程
  • 对存储属性赋值:可以在定义属性的时候,就给它赋初值。
  • 如果没有赋初值,就必须在我们的构造函数(init方法)里面赋值,否则会报错
class Person: NSObject {
    //直接给存储属性赋初值
    var name: String = "xiaowang"
    var age: Int = 20

    //系统默认会执行下面的父类构造函数,这里就可以不用手动调用
    //super.init()
}

//这个类是上面的Person类的子类
class Man: Person {
    var weight: Float
    var height: Float

    //在构造函数内给存储属性赋初值
    init (weight: Float, height: Float) {
        self.weight = weight
        self.height = height

        //父类没有重写构造函数,不用手动调用,此时系统会默认执行super.init()这条语句
        //如果父类重写了构造函数,则要像下面这样手动调用父类的构造函数.
        //注意:父类的构造函数要在自己的存储属性都被赋值后才能调用,否则会报错,这是因为
        //对象的构造过程是先构造自身的属性,确保自身的属性都初始化后才会构造父类的属性,一种从下而上的过程
        //super.init(age: 15)
    }
}

构造器(构造函数)

  • 所有的构造器的名字都叫 init
  • 构造器的功能是用来完成类的构造过程。生成我们需要对象
  • 如果我们的所有的存储属性都已经被初始化完成。那么,类会给我们创建一个默认的构造器 init()
  • 如果我们属性没有初始化完成,就需要我们自己去定义一个构造器
class Person: NSObject {
    var name: String
    var age: Int

    init (name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

let person0 = Person.init(name: "xiaowang", age: 20)
  • 以下四种属性在构造对象过程中,不需要考虑它们是否已被初始化
class Person {
    //1.已经初始化了的存储属性
    var name: String = "xiaowagn" 
    //2.计算属性
    var kindName: String {
        get {
            return "亲爱的\(name)"
        }
    }
    //可选属性
    var girlFriend: String?
    //懒加载属性
    lazy var pet: String = {
        return "xiaobao"
    }()
}

便利构造器

  • 便利构造器,就是简化类的构造过程的构造器
  • 用 convenience 关键字来修饰
class Person: NSObject {
    var name: String
    var age: Int
    var country: String
    var love: String
    var girlFriend: String

    init (name: String, age: Int, country:String, love: String, girlFriend: String) {
        self.name = name
        self.age = age
        self.country = country
        self.love = love
        self.girlFriend = girlFriend
    }

    //在类中创建了便利构造器,创建对象时不传递任何参数时就会调用这个便利构造器
    convenience override init(){
        self.init(name: "宝宝", age: 0, country: "china", love: "cry", girlFriend: "")
    }
}

//这里创建的对象传递了参数,调用的是常规的构造器
let baby = Person(name: "宝宝", age: 0, country: "china", love: "cry", girlFriend: "")

//这里创建的对象没有传递任何参数,调用了便利构造器
let baby2 = Person()

print("name: \(baby2.name), age:\(baby2.age)")


/*****拓展******/

//创建了一个加号按钮
let button = UIButton(type: .ContactAdd) //参数是枚举类型(感觉有点奇怪^-^)

KVC构造器

  • kvc 的原理是在运行时,动态地调用 setValue(value: AnyObject?, forKey key: String)
  • kvc 和可选的基本数据类型属性不兼容,记住!是可选的!
  • 如果属性是基本的数据类型,我们需要将其设为必须属性,并赋初值.
//Person.swift文件

//kvc 构造函数的执行过程
//1. setValuesForKeysWithDictionary
//2. 遍历我们的 dict 的 key 值,依次执行 setValue(value: AnyObject?, forKey key: String)
//3. 如果发现没有 key 值,会执行 `setValue(value: AnyObject?, forUndefinedKey key: String)`,如果没有重写该方法,就会直接崩溃

class Person: NSObject{
    var name: String?
    var age: Int = 0 //属性是基本数据类型,直接赋初值0

    //KVC构造器
    init (dict: [String: NSObject]){
        super.init()
        //调用以下方法实现KVC,实质是依次调用setValue方法,也就是上面描述的执行过程的第2步
        setValuesForKeysWithDictionary(dict)
    }

    //实现KVC依次执行的方法
    override func setValue(value: AnyObject?, forKey key: String) {
        super.setValue(value, forKey: key)
    }

    //当遍历传入的字典时,发现字典中的key在类中没有对应的属性,就会调用下面的方法
    override func setValue(value: AnyObject?, forUndefinedKey key: String) {
        print("key:\(key), value:\(value)")
    }
}
//ViewController.swift文件

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        //创建对象
        let person = Person(dict:["name":"xiaowang", "age": 20, "abc":"456"])
        print("name: \(person.name), age: \(person.age)")
    }
}

可失败构造器

  • 构造器没有按照预期成功构造对象时,可令其返回nil
  • 可失败构造器,在返回 nil 之前,也必须保证所有属性初始化
class Person: NSObject {
    var name: String
    var age: Int

    //多了个问号,表示可失败构造器
    init?(name: String, age: Int) {
        self.name = name
        self.age = age
        super.init()
        if age > 200 { //当符合这个条件时,可让构造器返回nil
            return nil
        }
    }
}

let person = Person(name: "xiaowang", age: 300)
//构造器返回nil,所有在构造器中初始化的变量值都为nil
print(person?.name) //result: nil
print(person?.age) //result: nil

构造器的继承规则

  • 如果子类没有实现任何父类的指定构造器,则继承所有的父类的指定构造器和便利构造器
  • 如果子类重写了所有的父类的指定构造器,则默认继承父类所有便利构造器
  • 如果没有全部重写父类的指定构造器,则父类的构造器一个也不继承
class Person:NSObject {
    var name: String
    var age: Int

    //指定构造函数
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    init(name: String) {
        self.name = name
        self.age = 25
    }

    //便利构造函数
    convenience override init() {
        self.init(name: "宝宝", age: 0)
    }
}

//没有没有实现任何父类的指定构造器,则继承所有的父类的指定构造器和便利构造器
class Man: Person{

}

let man = Man() //调用父类的便利构造器
print(man.name) //result:"宝宝"
print(man.age) //result:0

let man1 = Man(name: "xiaoming") //调用父类的第二个指定构造器
print(man1.name) //result:"xiaoming"
print(man1.age) //result:25

let man2 = Man(name: "xiaohua", age: 20)//调用父类的第一个指定构造器
print(man2.name) //result:"xiaohua"
print(man2.age) //result:20
class Person:NSObject {
    var name: String
    var age: Int

    //指定构造函数
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    init(name: String) {
        self.name = name
        self.age = 25
    }

    //便利构造函数
    convenience override init() {
        self.init(name: "宝宝", age: 0)
    }
}

//重写所有父类的指定构造函数,默认继承所有父类的便利构造器
class Man2: Person {

    //这里如果少重写一个父类的指定构造器,则下面无法调用父类的便利构造器
    //override 关键字表示重写父类的方法
    override init(name: String) {
        super.init(name: name)
    }

     override init(name: String, age: Int) {
        super.init(name: name, age: age)
    }

}

let man1 = Man2() //调用了父类的便利构造器
print(man1.name) //result:"宝宝"
print(man1.age) //result:0
class Person:NSObject {
    var name: String
    var age: Int

    //指定构造函数
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    init(name: String) {
        self.name = name
        self.age = 25
    }

    //便利构造函数
    convenience override init() {
        self.init(name: "宝宝", age: 0)
    }
}

//只重写了一部分父类的指定构造函数,父类的构造器一个也不会继承,也就是不能调用
class Man3: Person{

    convenience init() {
        self.init(name:"xiaoxiao", age:20)
    }

    //指定构造函数
    override init(name: String, age: Int) {
        super.init(name: name, age: age)
    }

}

let man1 = Man3() //调用的是自己的便利构造器
print(man1.name) //result:"xiaoxiao"
print(man1.age) //result:20

你可能感兴趣的:(swift,构造器)