Swift 結(jié)構(gòu)體 和 類 ⑤

??在Swift標(biāo)準(zhǔn)庫(kù)中,絕大多數(shù)的公開類型都是結(jié)構(gòu)體,而枚舉和類之占一小部分,比如:Bool、Int、Double、String、Array、Dictionary等常見類型都是結(jié)構(gòu)體

結(jié)構(gòu)體

1 結(jié)構(gòu)體初識(shí)

  • 所有結(jié)構(gòu)體都有一個(gè)編譯器自動(dòng)生成初始化器(ininiallizer, 初始化方法、構(gòu)造器、構(gòu)造方法)示例:
struct Date {
    var year : Int
    var month : Int
    var day : Int
    
}
var date = Date(year: 2020, month: 07, day: 24)
 //這里只是定義了Date結(jié)構(gòu)體,但是直接可以調(diào)用Date(year: 2020, month: 07, day: 24)
  • 編譯器會(huì)根據(jù)情況,可能會(huì)為結(jié)構(gòu)體生成多個(gè)初始化器,宗旨是:保證所有成員都有初始值,示例:
struct Point {
    var x : Int = 0
    var y : Int
    
}
var p1 = Point(x: 10, y: 20)  //正常
var p2 = Point(y: 20)//正常
var p2 = Point(x: 10)//報(bào)錯(cuò) Missing argument for parameter 'y' in call

2. 自定義初始化器

  • 一旦在定義結(jié)構(gòu)體時(shí)自定義了初始化器,則編譯器不會(huì)在幫它自動(dòng)生成其他初始化器,示例
struct Person {
    var name : String
    var age : Int
    init(name:String , age: Int) {
        self.name = name
        self.age = age
    }
}

1. 類初識(shí)

  • 類的定義和結(jié)構(gòu)體類似,但編譯器并沒有為類自動(dòng)生成可以傳入成員變量的初始化器,示例
class Student {
    var name : String
    var age : Int
}
  • 如果類的所有成員都在定義時(shí),指定了初始化值,則編譯器會(huì)為類生成無(wú)參的初始化器。示例
class Student {
    var name : String = "Jack"
    var age : Int = 0
    
}
var std = Student()

結(jié)構(gòu)體 與 類 的本質(zhì)區(qū)別(待補(bǔ)充

1. 結(jié)構(gòu)體是值類型(枚舉也是值類型),類是引用類型(指針類型··· )

  • 值類型:值類型賦值給 varlet 或者給函數(shù)傳參,是直接將所有內(nèi)容拷貝一份,屬于深拷貝
  • 引用類型: 引用賦值給 var、let或者給函數(shù)傳參,是將內(nèi)存地址拷貝一份,屬于淺拷貝。

注意:在Swift標(biāo)準(zhǔn)庫(kù)中,為了提升性能,String、Array、Dictionary、Set 采取了Copy On Write,
??1. 比如僅當(dāng)有 "寫" 操作時(shí),才會(huì)真正執(zhí)行拷貝操作。
對(duì)于標(biāo)準(zhǔn)庫(kù)值類型的賦值操作,Swift能確保最佳性能,所以沒有必要為了保證最佳性能來(lái)避免賦值
??2.不需要修改的變量盡量定義成let


// 值類型賦值 ;String、Array、Dictionary、Set也是結(jié)構(gòu)體類型,所以他們也屬于值類型
struct Point {
    var x : Int = 0
    var y : Int
    
}
func test(){
    var p1 : Point = Point(x: 10, y: 20)
    var p2 : Point = p1
    
    p2.x = 22
    p2.y = 33
    
    print(p1)//Point(x: 10, y: 20)
}


var s1 = "jack"
var s2 = s1
s2.append("_hi")
print(s1)// jack
print(s2)//jack_hi

2. 值類型 、引用類型 的 let

struct Point {
    var x : Int
    var y : Int
    
}

class Size {
    var width : Int
    var height : Int
    init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
}


let po1 = Point(x: 10, y: 20)
po1 = Point(x: 2, y: 3)  //報(bào)錯(cuò):Cannot assign to value: 'po1' is a 'let' constant
po1.x = 2 //報(bào)錯(cuò):Cannot assign to value: 'po1' is a 'let' constant
po1.y = 3 //報(bào)錯(cuò):Cannot assign to value: 'po1' is a 'let' constant

let si1 = Size(width: 10, height: 20)
si1 = Size(width: 2, height: 3)// 報(bào)錯(cuò):Cannot assign to value: 'si1' is a 'let' constant
si1.width = 2
si1.height = 3

注意:對(duì)于引用類型 si ,其實(shí)存放的是一個(gè)地址,指向堆一個(gè)堆內(nèi)存空間,
let si 指的是不能修改這個(gè)si指向的地址內(nèi)存,si1.width = 2 si1.height 實(shí)際上是改的對(duì)應(yīng)堆空間里面的值,并沒有修改si的地址指向,所以并不會(huì)報(bào)錯(cuò)。


嵌套類型

??類似于內(nèi)部類。如果某個(gè)類只在某個(gè)類里面使用時(shí),則可以使用嵌套類型。

struct PersonObj {
    enum sex : String {
        case man = "1", woman = "2"
    }
    enum nation : Int {
        case hanzu = 1 , manzu = 2 , weiwuerzu = 3
    }
}

print(PersonObj.sex.man.rawValue)

var sextype = PersonObj.sex.man
sextype = .woman

枚舉、結(jié)構(gòu)體、類都可以定義方法

  • 一般把定義在枚舉、結(jié)構(gòu)體、類內(nèi)部的函數(shù),叫做方法
  • 方法不占用對(duì)象的內(nèi)存空間,方法的本質(zhì)就是函數(shù),方法和函數(shù)都存放在代碼段
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容