美文网首页
15.构造过程

15.构造过程

作者: LucXion | 来源:发表于2021-07-19 10:48 被阅读0次

存储属性初始化

为存储型属性分配默认值或者在构造器中设置初始值时,它们的值是被直接设置的,不会触发任何属性观察者。

形参命名和实参标签

构造器并不像函数和方法那样在括号前有一个可辨别的方法名。因此在调用构造器时,主要通过构造器中形参命名和类型来确定应该被调用的构造器。正因如此,如果你在定义构造器时没有提供实参标签,Swift 会为构造器的每个形参自动生成一个实参标签。

struct Person {
    var name:String
    var age:Int
    // 没有实参标签,有两个形参name、age
    init(_ name:String,_ age:Int){
        self.name = name
        self.age = age
    }
}

常量属性

对于类的实例来说,它的常量属性只能在定义它的类的构造过程中修改;不能在子类中修改。

结构体的逐一成员构造器

struct Person {
    var name:String
    var age:Int = 12
    /*
     自动生成两个逐一成员构造器
     init(name:)// 因为age已经设置了默认值
     init(name:age:)//如果age是常量,那么就不会自动生成这个构造器
     */
}

指定构造器和便利构造器

指定构造器是类中最主要的构造器。一个指定构造器将初始化类中提供的所有属性,并调用合适的父类构造器让构造过程沿着父类链继续往上进行。类倾向于拥有极少的指定构造器,但每个类都必须至少拥有一个指定构造器。

便利构造器是类中比较次要的、辅助型的构造器。你可以定义便利构造器来调用同一个类中的指定构造器,并为部分形参提供默认值。你应当只在必要的时候为类提供便利构造器,比方说某种情况下通过使用便利构造器来快捷调用某个指定构造器,能够节省更多开发时间并让类的构造过程更清晰明了。

class Person {
    var name:String = ""
    var age:Int = 1
    init(parama:String){
        // 指定构造器
    }
    convenience init(data:String){ // 便利构造器 convenience
        self.init(parama: data)// 便利构造器内必须调用指定构造器
    }
}

继承关系下的指定构造器和便利构造器

  • 指定构造器必须总是向上代理

  • 便利构造器必须总是横向代理


两段式构造过程

Swift 中类的构造过程包含两个阶段。第一个阶段,类中的每个存储型属性赋一个初始值。当每个存储型属性的初始值被赋值后,第二阶段开始,它给每个类一次机会,在新实例准备使用之前进一步自定义它们的存储型属性。

两段式构造过程的使用让构造过程更安全,同时在整个类层级结构中给予了每个类完全的灵活性。两段式构造过程可以防止属性值在初始化之前被访问,也可以防止属性被另外一个构造器意外地赋予不同的值。

阶段 1

  • 类的某个指定构造器或便利构造器被调用。

  • 完成类的新实例内存的分配,但此时内存还没有被初始化。

  • 指定构造器确保其所在类引入的所有存储型属性都已赋初值。存储型属性所属的内存完成初始化。

  • 指定构造器切换到父类的构造器,对其存储属性完成相同的任务。

  • 这个过程沿着类的继承链一直往上执行,直到到达继承链的最顶部。

  • 当到达了继承链最顶部,而且继承链的最后一个类已确保所有的存储型属性都已经赋值,这个实例的内存被认为已经完全初始化。此时阶段 1 完成。

阶段 2

  • 从继承链顶部往下,继承链中每个类的指定构造器都有机会进一步自定义实例。构造器此时可以访问 self、修改它的属性并调用实例方法等等。

  • 最终,继承链中任意的便利构造器有机会自定义实例和使用 self

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

指定构造器:优先保证当前类内声明的属性被赋值(第一阶段) -> 调用父类的指定构造器(第一阶段)-> 给父类的属性赋新值(第二阶段)

便利构造器:调用其他构造器(第一阶段) -> 赋新值(第二阶段)

构造器的继承和重写

Swift 中的子类默认情况下不会继承父类的构造器

如果子类的构造器没有在阶段 2 过程中做自定义操作,并且父类有一个无参数的指定构造器,你可以在所有子类的存储属性赋值之后省略 super.init() 的调用。

重写的不能是父类的便利构造方法

class Food {
    var name: String
    init(name: String) {  // 指定构造器
        self.name = name
    }
    convenience init() { // 便利构造器 convenience
        self.init(name: "[Unnamed]")// 便利构造器内必须调用指定构造器
    }
}
// 子类中没有新增的未初始化属性,如果没有指定构造器,默认继承父类的指定构造器
class RecipeIngredient: Food {
    var quantity: Int
    init(name: String, quantity: Int) {
        self.quantity = quantity
        super.init(name: name)
    }
    override convenience init(name: String) {//便利构造器,
        self.init(name: name, quantity: 1)
    }
}

let oneMysteryItem = RecipeIngredient()// 调用继承自父类的无参便利构造器 -> 子类便利构造器(重写的父类指定构造器) -> 子类指定构造器 -> 父类指定构造器

可失败的构造器

class Person {
    var name:String
    init(){
        print("3")
        self.name = "[unName]"
    }
    init?(nameCannotBeEmpty name:String){
        print("2")
        if name.isEmpty {
            return nil
        }
        self.name = name
    }
}

class Student:Person {
    var id : Int = 0
    init?(id:Int,name:String){
        print("1")
        if id <= 0 {
            return nil
        }
        self.id = id
//          super.init(nameCannotBeEmpty: name)  可以调用父类指定构造器,也可以调用父类的可失败构造器
        super.init()
    }
}
var s = Student.init(id: 10086, name: "Li")
print(s?.name,s?.id)

必要构造器

在类的构造器前添加 required 修饰符表明所有该类的子类都必须实现该构造器

通过闭包或者全局函数给存储属性设置默认值

如果你使用闭包来初始化属性,请记住在闭包执行时,实例的其它部分都还没有初始化。这意味着你不能在闭包里访问其它属性,即使这些属性有默认值。同样,你也不能使用隐式的 self 属性,或者调用任何实例方法。

相关文章

  • 15.构造过程

    存储属性初始化 为存储型属性分配默认值或者在构造器中设置初始值时,它们的值是被直接设置的,不会触发任何属性观察者。...

  • Swift5.1构造过程&析构过程

    14.构造过程 构造过程 15.构析过程 析构过程原理析构过程:析构器只适⽤于类类型,当一个类的实例被释放之前,析...

  • 构造过程

    本页包含内容: [TOC] 构造过程是使用类、结构体或枚举类型的实例之前的准备过程。在新实例可用前必须执行这个过程...

  • 构造过程

    构造过程是在使用类,结构和枚举实例之前的准备过程,存储属性的赋值和一些准备工作。 构造器 在创建实例的时候调用的函...

  • 构造过程

    构造过程 当你为存储型属性设置默认值或者在构造器中为其赋值时,它们的值是被直接设置的,不会触发任何属性管擦起。 自...

  • iOS开发之Swift篇(12)—— 构造和析构

    目录 版本 构造过程 析构过程 版本 Xcode 11.3.1Swift 5.1.3 构造过程 构造过程是使用类、...

  • 2019-12-02 swift5 个人笔记 ③

    25,构造过程 构造过程是使用类 结构体 枚举类型之前的准备过程,在使用新实例之前构造过程是必须得.与oc的构造器...

  • Swift学习—— initialization构造过程

    Swift学习—— initialization构造过程Swift学习—— initialization构造过程

  • Initialization in Swift

    简介 *自定义构造过程 *默认构造器 *值类型的构造器代理 *类的继承和构造过程 *可失败构造器 *必需构造器 *...

  • Swift - 构造过程

    构造过程是使用类、结构体或枚举类型的实例之前的准备过程。在新实例可用前必须执行这个过程,具体操作包括设置实例中每个...

网友评论

      本文标题:15.构造过程

      本文链接:https://www.haomeiwen.com/subject/nhjbpltx.html