??在Swift標(biāo)準(zhǔn)庫中,絕大多數(shù)的公開類型都是結(jié)構(gòu)體驯妄,而枚舉和類之占一小部分荷并,比如:Bool、Int青扔、Double源织、String、Array微猖、Dictionary等常見類型都是結(jié)構(gòu)體
結(jié)構(gòu)體
1 結(jié)構(gòu)體初識
- 所有結(jié)構(gòu)體都有一個編譯器自動生成初始化器(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)
- 編譯器會根據(jù)情況,可能會為結(jié)構(gòu)體生成多個初始化器当悔,宗旨是:保證所有成員都有初始值傅瞻,
示例:
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)//報錯 Missing argument for parameter 'y' in call
2. 自定義初始化器
- 一旦在定義結(jié)構(gòu)體時自定義了初始化器,則編譯器不會在幫它自動生成其他初始化器盲憎,
示例
struct Person {
var name : String
var age : Int
init(name:String , age: Int) {
self.name = name
self.age = age
}
}
類
1. 類初識
- 類的定義和結(jié)構(gòu)體類似嗅骄,但編譯器并沒有為類自動生成可以傳入成員變量的初始化器,
示例
class Student {
var name : String
var age : Int
}
- 如果類的所有成員都在定義時饼疙,指定了初始化值溺森,則編譯器會為類生成無參的初始化器。
示例
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)庫中独榴,為了提升性能,String奕枝、Array棺榔、Dictionary、Set
采取了Copy On Write隘道,
??1. 比如僅當(dāng)有 "寫" 操作時症歇,才會真正執(zhí)行拷貝操作。
對于標(biāo)準(zhǔn)庫值類型的賦值操作薄声,Swift能確保最佳性能当船,所以沒有必要為了保證最佳性能來避免賦值
??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) //報錯:Cannot assign to value: 'po1' is a 'let' constant
po1.x = 2 //報錯:Cannot assign to value: 'po1' is a 'let' constant
po1.y = 3 //報錯:Cannot assign to value: 'po1' is a 'let' constant
let si1 = Size(width: 10, height: 20)
si1 = Size(width: 2, height: 3)// 報錯:Cannot assign to value: 'si1' is a 'let' constant
si1.width = 2
si1.height = 3
注意:
對于引用類型 si 竞思,其實(shí)存放的是一個地址表谊,指向堆一個堆內(nèi)存空間,
let si 指的是不能修改這個si指向的地址內(nèi)存盖喷,si1.width = 2 si1.height 實(shí)際上是改的對應(yīng)堆空間里面的值爆办,并沒有修改si的地址指向,所以并不會報錯课梳。
嵌套類型
??類似于內(nèi)部類距辆。如果某個類只在某個類里面使用時,則可以使用嵌套類型暮刃。
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ù),叫做方法
- 方法不占用對象的內(nèi)存空間,方法的本質(zhì)就是函數(shù)背犯,方法和函數(shù)都存放在代碼段