Day 10 Swift语法-进阶篇(3/5)-Initialization

我们在定义类别或结构时,有时候会需要做初始化的动作,简单说,就是给一个值,譬如我们在写C的时候,如果我们要对一个值去做增加或减少的时候,我们会先给一个初始值,通常是0,譬如这样:

int value = 0
for(int i  = 0; i<10; i++)
{
    value = value + i;
}

透过给初始值的方式,编译器才知道,我们要累加的值是从0开始。

以此类推,如果我们这样在class里面宣告一个变数

这个时候编译器就会报错说你没有初始化,接下来我们把它初始化:

class Example1 {
    
    var heigth = Int()
}

这边的Int()就是给他一个值为0,当然我们也可以搭配自定义的初始化,例如这样:

class Example2 {
    
    var height: Int
    
    init(height : Int) {
        self.height = height
    }
}

透过init(Initialization)这样一来我们就可以自订我们的初始化,但须留意的是,我们在这里只宣告height是个Int型态,并没有给他初始值,我们加入下面的程序码

let tom = Example2(height: 180)
print(tom)

这样一来我们就把180这个值给到height了

指定初始化跟便捷初始化(Designated and Convenience Initializer):

一般我们所使用的init都称为Designated Initializer,但如果需要遇到补充的参数,而他也需要被初始化的时候,我们就可以使用Convenience Initializer了,譬如这样:

lass Student{
    var height: Double
    var weight: Double
    var studentName: String
    
    init(height:Double, weight: Double, studentName: String){
        self.height = height
        self.weight = weight
        self.studentName = studentName
    }
    
    convenience init(newStudentName: String) {
        self.init(height: 175.0, weight: 60.0, studentName: newStudentName)
    }
    
}

然後我们宣告一个变数,然後把里面的参数打印出来

透过这张图,我们可以得到一个结果,因为我们已经在convenience init初始化我们的heigth跟weight了,但是我们没有告诉编译器studentName是什麽,我们只跟他说,我们用了一个newStudentName而他的值是String,所以,我们在最底下就必续给他一个值(学生姓名),给他值之後,他就会传给convenience init,然後再给designated init,也就是,假设我们给peter,他就会是 peter -> newStudentName -> studentName,所以我们print是印出studentName~

var peter = Student(newStudentName: "peter")
print(peter.studentName)
//peter

虽然height跟weight,不能重新在下面给值,原因是因为已经被convenience init初始化过了,但是我们可以取用他的值,譬如这样:

print(peter.height)
//175.0

这时候你会想说,可是我坚持要给height跟weight一个新的值,可不可以?答案是可以,但是我们就是透过一开始的designated init去给他值(上面图片的第一行(height:weight:studentName:)),所以们连学生名字都要自己取一个新的,譬如:

var tom = Student(height: 154, weight: 162, studentName: "tom")
print(tom.height)
//154.0

当然,一个class我们通常只会使用一个,或两个designated init,但是convenience init可以在一个class里面同时多个使用(3个以上),譬如我们在弄一个convenience init并结合之前的 convenience init跟designated init来做个完整的练习:

import UIKit

class Student{
    var height: Double
    var weight: Double
    var studentName: String
    
    init(height:Double, weight: Double, studentName: String){
        self.height = height
        self.weight = weight
        self.studentName = studentName
    }
    
    convenience init(newStudentName: String) {
        self.init(height: 175.0, weight: 60.0, studentName: newStudentName)
    }
    
    convenience init(newStudentName2: String) {
        self.init(height: 162, weight: 50.0, studentName: newStudentName2)
    }
    
}

var peter = Student(newStudentName: "peter")
print(peter.studentName)
print("peter's height is \(peter.height) cm")

var tom = Student(height: 154, weight: 162, studentName: "tom")
print(" ")
print(tom.studentName)
print("toms's height is \(tom.height) cm")

var allen = Student(newStudentName2: "allen")
print(" ")
print(allen.studentName)
print("allen's weight is \(allen.weight) kg")

结果如下:

我们透过这个方式可以印证如swift官方文件所说的:
“Designated initializers must always delegate up
Convenience initializers must always delegate across“
这句话用他的图片来看就是这样:

这个情况是你有一个父类别,跟一个子类别,父类别里有一个designated跟两个convenience init,子类别有两个designated init 跟一个convenience init,可以观察下片头的方向,他在讲的就是:
convenience init是横向(左右)传值
designated则是纵向(上下)传值

而当你有多个class则是长这样

最後补充三个规则:
Rule 1
A designated initializer must call a designated initializer from its immediate superclass.
指定初始化只能从父类别叫另一个指定初始化器
Rule 2
A convenience initializer must call another initializer from the same class.
便捷初始化器调用另一个初始化器(有可能是指定初始化器也可能是另个便捷初始化器),必须是在同一个class
Rule 3
A convenience initializer must ultimately call a designated initializer.
便捷初始化器最终一定会呼叫一个指定初始化器(不管子类别还是父类别)


<<:  Day 22 - Rancher Fleet 架构介绍

>>:  DAY 10-《区块密码2》AES(2)-密钥排程及安全性

Day 21 - canvas 玩拼图 P5.js

今天本来要带大家玩 用 canvas 完成拼图 参考的范例在这里 很可惜又是时间不足 先把目前完成的...

[Day9] Vite 出小蜜蜂~撞击行为 Collision Behavior!

Day9 Collision Behavior 当 Laser 跟 Squid 相互撞击时, 我们想...

[Day 5] Vue的数据与方法

昨天简单介绍了Vue的 响应式,关於响应式的基本介绍可以直接看昨天那篇,这边就不再赘述(╹ڡ╹ )。...

D8. 学习基础C、C++语言

D8. 题目练习(uva11777) #include <stdio.h> #inclu...

【後转前要多久】# Day15 CSS -难东西 (伪元素)

这篇纪录了CSS中不算少见、却也有些难理解的东西 DOM Tree之中不涵盖伪元素及伪类别,可以对D...