??在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)體是值類型(枚舉也是值類型),類是引用類型(指針類型··· )
-
值類型:值類型賦值給var、let或者給函數(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ù)都存放在代碼段