結(jié)構(gòu)體
在Swift 標(biāo)準(zhǔn)庫中,絕大多數(shù)的公開類型都是結(jié)構(gòu)體号坡,而枚舉和類只占很小一部分?
比如Bool懊烤、Int、Double筋帖、 String奸晴、Array、Dictionary等常見類型都是結(jié)構(gòu)體
struct Date {
????var year: Int
????var month: Int
????var day: Int
}
var date = Date(year: 2019, month: 6, day: 23)
所有的結(jié)構(gòu)體都有一個(gè)編譯器自動(dòng)生成的初始化器(initializer日麸,初始化方法寄啼、構(gòu)造器、構(gòu)造方法)?
在第6行調(diào)用的代箭,可以傳入所有成員值墩划,用以初始化所有成員(存儲(chǔ)屬性,Stored Property)
結(jié)構(gòu)體的初始化器
編譯器會(huì)根據(jù)情況嗡综,可能會(huì)為結(jié)構(gòu)體生成多個(gè)初始化器乙帮,宗旨是:保證所有成員都有初始值
可選項(xiàng)都有個(gè)默認(rèn)值nil ?因此可以編譯通過
struct Point {
? ? var x: Int?
? ? var y: Int?
}
var p1 = Point(x: 10, y: 10)
var p2 = Point(y: 10)
var p3 = Point(x: 10)
var p4 = Point()
自定義初始化器:一旦在定義結(jié)構(gòu)體時(shí)自定義了初始化器,編譯器就不會(huì)再幫它自動(dòng)生成其他初始化器
窺探初始化器的本質(zhì)
以下2段代碼完全等效
? struct Point {
? ? var x: Int = 0
var y: Int = 0 }
var p = Point()
----------------
struct Point {
? ? var x: Int
? ? var y: Int
????init() { x=0 y=0
} }
var p = Point()
結(jié)構(gòu)體內(nèi)存結(jié)構(gòu)
struct Point {
? ? var x: Int = 0
var y: Int = 0
? ? var origin: Bool = false
}
print(MemoryLayout<Point>.size) // 17
print(MemoryLayout<Point>.stride) // 24
print(MemoryLayout<Point>.alignment) // 8
類?
類的定義和結(jié)構(gòu)體類似极景,但編譯器并沒有為類自動(dòng)生成可以傳入成員值的初始化器
結(jié)構(gòu)體與類的本質(zhì)區(qū)別
結(jié)構(gòu)體是值類型(枚舉也是值類型)察净,類是引用類型(指針類型)
? class Size {
? ? var width = 1
? ? var height = 2
}
struct Point {
? ? var x = 3
? ? var y = 4
}
func test() {
? ? var size = Size()
? ? var point = Point()
}
值類型的賦值操作
????在Swift標(biāo)準(zhǔn)庫中驾茴,為了提升性能,String氢卡、Array锈至、Dictionary、Set采取了Copy On Write的技術(shù)?
????比如僅當(dāng)有“寫”操作時(shí)译秦,才會(huì)真正執(zhí)行拷貝操作
????對于標(biāo)準(zhǔn)庫值類型的賦值操作峡捡,Swift 能確保最佳性能,所有沒必要為了保證最佳性能來避免賦值
????建議:不需要修改的筑悴,盡量定義成let
var s1 = "Jack"
var s2 = s1
s2.append("_Rose")
print(s1) // Jack
print(s2) // Jack_Rose
-----------------------
var a1 = [1, 2, 3]
var a2 = a1
a2.append(4)
a1[0] = 2
print(a1) // [2, 2, 3]
print(a2) // [1, 2, 3, 4]
--------------------
var d1 = ["max" : 10, "min" : 2]
var d2 = d1
d1["other"] = 7
d2["max"] = 12
print(d1) // ["other": 7, "max": 10, "min": 2]
print(d2) // ["max": 12, "min": 2]
引用類型
????引用賦值給var们拙、let或者給函數(shù)傳參,是將內(nèi)存地址拷貝一份 p類似于制作一個(gè)文件的替身(快捷方式阁吝、鏈接)砚婆,指向的是同一個(gè)文件。屬于淺拷貝(shallow copy)
class Size {
? ? var width: Int
var height: Int
init(width: Int, height: Int) {
? ? ? ? self.width = width
? ? ? ? self.height = height
? ? }
}
func test() {
var s1 = Size(width: 10, height: 20) var s2 = s1
}
s2.width = 11
s2.height = 22
// s1.width和s1.height是11 22
對象的堆空間申請過程
在Swift中求摇,創(chuàng)建類的實(shí)例對象射沟,要向堆空間申請內(nèi)存,大概流程如下 Class.__allocating_init()?
libswiftCore.dylib:_swift_allocObject_?
libswiftCore.dylib:swift_slowAlloc?
libsystem_malloc.dylib:malloc
在Mac与境、iOS中的malloc函數(shù)分配的內(nèi)存大小總是16的倍數(shù)
通過class_getInstanceSize可以得知:類的對象至少需要占用多少內(nèi)存
class Point? {
? ? var x = 11
? ? var test = true
????var y = 22 }
var p = Point()
class_getInstanceSize(type(of: p)) // 40
class_getInstanceSize(Point.self) // 40
引用類型的賦值操作
class Size {
? ? var width: Int
? ? var height: Int
? ? init(width: Int, height: Int) {
? ? ? ? self.width = width
? ? ? ? self.height = height
? ? }
}
var s1 = Size(width: 10, height: 20)
s1 = Size(width: 11, height: 22)
值類型验夯、引用類型的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
? ? }
}
嵌套類型
struct Poker {
? ? enum Suit : Character {
????????????case spades = "?", hearts = "?", diamonds = "?" , clubs = "?"}
????enum Rank : Int {
????????case two = 2, three, four, five, six, seven, eight, nine, ten
? ? ? ? case jack, queen, king, ace
? ? }
}
print(Poker.Suit.hearts.rawValue)
var suit = Poker.Suit.spades
suit = .diamonds
var rank = Poker.Rank.five
rank = .king
枚舉、結(jié)構(gòu)體摔刁、類都可以定義方法
一般把定義在枚舉挥转、結(jié)構(gòu)體、類內(nèi)部的函數(shù)共屈,叫做方法
方法占用對象的內(nèi)存么? ?不占用?
方法的本質(zhì)就是函數(shù)?
方法绑谣、函數(shù)都存放在代碼段
class Size {
? ? var width = 10
? ? var height = 10
? ? func show() {
????print("width=\(width), height=\(height)") }
}
let s = Size()
s.show() // width=10, height=10
-------------------------------
struct Point {
? ? var x = 10
? ? var y = 10
????func show() { print("x=\(x), y=\(y)")
} }
let p = Point()
p.show() // x=10, y=10
--------------------
enum PokerFace : Character {
? ??case spades = "?", hearts = "?", diamonds = "?", clubs = "?"
????func show() { print("x=\(x), y=\(y)")}?
}
let pf = PokerFace.hearts?
pf.show() // face is ?