美文网首页Swift
iOS Swift5 构造函数分析(二):init 构造函数在s

iOS Swift5 构造函数分析(二):init 构造函数在s

作者: 青叶小小 | 来源:发表于2021-02-27 00:04 被阅读0次

    一、前言

    上篇《关键字 designated、convenience、required》中,我们了解到了 swift 在构造器这块给我们带来的新特性,结合我们之前的一篇《浅析结构体(struct)与类(class) 》,我们今天就来聊聊在 struct 与 class 中的应用与不同。

    二、默认构造器

    先来个灵魂拷问:何谓『默认构造器』?
    不显式定义给出构造器(构造函数),由系统自动添加生成!(在 Swift 中,默认构造器就是 designated 构造器)

    是不是光看文字理解有点困难?那我就来个 demo 演示。

    2.1、struct

    struct DemoStruct {
        var name: String
        var age: Int
    }
    

    没有构造方法(init),但我们可以这么来初始化使用:

    struct-before.png

    当我们输入『左括号』时,Xcode 自动提示,给了我们一个唯一的初始化方法,这个就是『默认构造器』,我们也可以显式这样来创建:

    struct-init.png

    即通过 init 构造器来初始化,但同样,Xcode 也提示我们有两个参数。为啥是有参数,而不是无参,例如:DemoStruct.init() ?

    2.1.1、逐一成员构造器

    这是 Swift 规范:当我们没有显式指定至少一个 init 构造器时,swift 会为我们添加一个默认构造器,该构造器的入参即是 struct 中的所有成员!

    上面例子中,我们定义了两个成员,分别是:name 和 age,因此,swift 会按照从上到下,依次将其纳入到默认构造器中,即创建了如下构造器:

    swift-struct.png

    如果 struct 讲到这里就完了,是不是很没意思?如果你认为这就完了,你就『Too Young Too Simple』了!

    如果我们的 struct 中有很多成员变量,虽然 swift 会为我们创建默认构造器,但是,我们在使用时,每个参数都需要传入,使用就会很麻烦,那有没有其它方式呢?例如,初始化时,我只想传 name :

    optional.png

    上面的代码片段没有报错,运行无任何问题!

    我们有三种解决方式:

    • 可选参数默认构造器;
    • 默认参数默认构造器;
    • 扩展构造器;

    2.1.2、可选参数默认构造器

    param-nil.png

    我们看到,age 的类型是 Int? ,但可为 nil;因此,我们可以在初始化时,只需要传入强制必要的参数:

    struct-param-nil.png

    2.1.3、默认参数默认构造器

    名字有点绕,但效果很简单:

    param-def.png

    2.1.4、扩展构造器

    扩展,即 extension ,swift 提供的一种方式,无论是 struct 还是 class 都可以使用:

    // 扩展 struct
    extension DemoStruct {
        // 重载一个构造器
        // 该构造器调用默认构造器
        init(name: String) {
            self.init(name: name, age: 18)
        }
    }
    

    执行结果如下:

    struct-result.png

    2.2、class

    同样,先来定义一个 class,代码如下:

    class DemoClass {
        var name: String
        var age: Int
    }
    

    如果仅是这样,Xcode 会立即提示报错(类没有构造器):

    no-init.png

    我们至少需要显式指定(explicit designated)一个构造器,对于 DemoClass,我们要按照类似 struct 的逐一成员构造器那样,定义一个构造器,如果只构造部分成员的构造器,则会如下报错:

    not-all-init.png

    该错误提示:没有初始化所有的成员。对于这种情况,我们有三种方式来完成:

    • 将 age 设置为可默认为 nil 类型(等同于 2.1.2);
    • 定义 age 时就给定默认值(等同于 2.1.3);
    • 在构造器中给定默认值(如下代码所示);
    class DemoClass {
        var name: String
        var age: Int
        
        init(name: String) {
            self.name = name
            // 构造器中给定默认值
            self.age = -1
        }
    }
    

    class 要求必需显式指定一个构造器,而 struct 则是由 swift 自动添加。同样,class 也可以通过扩展(extension)来重载构造器(注:扩展类的构造器,是需要便利的,即添加关键字:convenience):

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

    我们执行看下结果:

    class-result.png

    三、可失败构造器

    类似 Kotlin 都有一种类型叫可null类型,Swift 也不甘落后,也有可空类型,而且 Swift 更进一步,允许在创建变量(struct)、对象(class)或枚举时,返回空对象(即创建失败,返回为 nil )。

    \color{red}{注意:根据官方文档,明确说了目前只有 struct、class、enum 可以在创建时返回 nil !}

    • 什么叫空类型?
    // T 代表任何类型
    // variable 代表变量、对象
    var variable: T? = nill
    
    // 例如:
    var str: String? = nil // 可 nil 字符串
    var num: Int? = nil    // 可 nil 整型
    
    • 如何定义可失败构造器?

    可失败构造器定义非常简单,只需要在 init 后加个问号,即:init? 即可,例如下图:

    define-init-nil.png

    我们可以看到,我们定义了一个可失败构造器,如果创建 Person 时,传入的字符串是『空字符串』,那么我们就返回 nil,否则就成功创建。从上图中,我们还能发现,可失败构造器的返回类型是:T?,在上面的例子中,返回类型是 Person?,即代表可能为 nil 。

    dif-use-init-nil.png

    上图是我们的测试代码,执行后打印结果非常清楚。对于 class 或者 enum ,与 struct 类似,我就不再演示,大家可自行测试。

    四、个人感想

    可人有些朋友要问:为何要花如此大的力气来分析 struct 和 class ?难道就是因为 Swift 新增了 struct 所以才写这些么?

    不,因为我在做《iOS Swift5从0到1系列》中,发现每当我实现一些功能时,就会或多或少涉及到一些 Swift 的新特性,虽然这些特性在 Swift 一出来就有,但是,我不确定大家都非常的了解熟悉,因此,但凡涉及到 Swift 中新的知识点,我都会单独开一些分支系列来提前讲解分析,希望大家能够一点一点的学习与吸收,而不是我一下子抛出很多新的知识点,导致大家难以消化吸收,影响心情放中途放弃。

    Swift 其实非常简单,我希望让大家和我一起共同成长进步,还可以快乐的交流,并且,本着我的博客中,所有的文章都是高质量,且可吸收(无论是 iOS 还是 Java、Android 或者 H5),因此,我会在讲解主线的同时,穿插不同支线;同时,一篇高质量的博文也要好几天(哪怕是分支内容),因此,希望大家不要心急。

    谢谢!

    相关文章

      网友评论

        本文标题:iOS Swift5 构造函数分析(二):init 构造函数在s

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