// 1.結(jié)構(gòu)體
func test_struct() {
// 在swift標(biāo)準(zhǔn)庫(kù)中,絕大數(shù)公開的類都是結(jié)構(gòu)體,枚舉和類只占一小部分
// Bool、Int、Double、String、Array、Dictionary等常見(jiàn)類型都是結(jié)構(gòu)體
struct Date {
var year: Int
var month: Int
var day: Int
var stringDesc: String {
get {
return String(format: "%04d-%02d-%02d", year, month, day)
}
}
}
// 編譯器會(huì)默認(rèn)為結(jié)構(gòu)體生成一個(gè)初始化器,參數(shù)包含所有的存儲(chǔ)屬性
let date = Date(year: 2019, month: 7, day: 11)
print("Date is \(date)")
print("Datedesc is \(date.stringDesc)")
// 編譯器根據(jù)情況自動(dòng)為結(jié)構(gòu)體生成不同的的初始化器
// 具體情況視成員屬性而定,宗旨:所有存儲(chǔ)屬性創(chuàng)建出來(lái)都能被初始化
struct Point1 {
var x: Int
var y: Int
// 自動(dòng)生成(保證x和y能被初始化)
// Point1(x: <#T##Int#>, y: <#T##Int#>)
}
let p1 = Point1(x: 1, y: 1)
struct Point2 {
var x: Int = 0
var y: Int
// 自動(dòng)生成(保證y能被初始化)
// Point1(x: <#T##Int#>, y: <#T##Int#>)
// Point2(x: <#T##Int#>)
}
let p21 = Point2(x: 2, y: 2)
let p22 = Point2(y: 2)
struct Point3 {
var x: Int = 0
var y: Int = 0
// 自動(dòng)生成(x和y都已經(jīng)初始化了,不許要在保證,因此可以生成一下幾個(gè)構(gòu)造方法)
// Point3()
// Point3(x: <#T##Int#>, y: <#T##Int#>)
// Point3(x: <#T##Int#>)
// Point3(y: <#T##Int#>)
}
let p31 = Point3()
let p32 = Point3(x: 2, y: 2)
let p33 = Point3(x: 2)
let p34 = Point3(y: 3)
// 當(dāng)自己定義了初始化函數(shù)后,編譯器不會(huì)再自動(dòng)生成其它初始化函數(shù)
struct Point4 {
var x: Int = 0
var y: Int = 0
// Point4(x: <#T##Int#>, y: <#T##Int#>)
init(x: Int, y: Int) {
self.x = x
self.y = y
}
// 由于自定義了初始化器,以下三個(gè)構(gòu)造器編譯器不會(huì)生成
// Point4()
// Point4(x: <#T##Int#>)
// Point4(y: <#T##Int#>)
}
let p41 = Point4(x: 2, y: 2)
// 初始化成員值和構(gòu)造器的本質(zhì)
/**
事實(shí)上,雖然Test1中在定義成員的時(shí)候給了初始值,但a和b發(fā)生初始化的時(shí)機(jī)在init方法中
即Test1中會(huì)自動(dòng)生成類似Test2中的init方法,Test1和Test2完全等價(jià)
*/
struct Test1 {
var a: Int = 0
var b: Int = 0
}
let t1 = Test1()
struct Test2 {
var a: Int
var b: Int
init() {
self.a = 0
self.b = 0
}
}
let t2 = Test2()
}
test_struct()
// 2.類
func test_class() {
// 類在初始化成員值時(shí)的原理和結(jié)構(gòu)體相同,都是在無(wú)參init方法中
// 默認(rèn)情況下,編譯器不會(huì)幫類生成初始化構(gòu)造器
/**
class Size1 {
var w: Int
var h: Int
// 注意:該類沒(méi)有任何構(gòu)造器
}
*/
/**
class Size2 {
var w = 10
var h: Int
}
*/
// 當(dāng)且僅當(dāng)類的所有成員都有初始值的時(shí)候,編譯器才會(huì)為類生成無(wú)參構(gòu)造方法
class Size3 {
var w = 10
var h = 20
}
let s3 = Size3()
// 同結(jié)構(gòu)體,一下兩段代碼完全等效[Size4 和 Size5 等效]
class Size4 {
var a: Int = 0
var b: Int = 0
}
let s4 = Size4()
class Size5 {
var a: Int
var b: Int
init() {
self.a = 0
self.b = 0
}
}
let s5 = Size5()
}
test_class()
// 3.結(jié)構(gòu)體和類的本質(zhì)區(qū)別
func test_struct_class() {
// (1)結(jié)構(gòu)和枚舉:值類型
// 創(chuàng)建對(duì)象,在哪里創(chuàng)建對(duì)象,就在哪里開辟對(duì)象需要的內(nèi)存空間
// (2)類:引用類型(指針類型)
// 創(chuàng)建對(duì)象,對(duì)象需要的內(nèi)存通常開辟堆空間,而在創(chuàng)建的地方使用一個(gè)指針指向該堆空間
// 值類型
struct sPoint1 {
var x = 10
var y = 30
}
let sp1 = sPoint1()
/**
sp1 的結(jié)構(gòu)
┏━━━━━━━┓
┃ x(10) ┃
┃ y(30) ┃
┗━━━━━━━┛
如果在函數(shù)內(nèi)部創(chuàng)建sp1,則在棧空間開辟 16個(gè)字節(jié)
如果在全局區(qū)創(chuàng)建sp1,則在數(shù)據(jù)段開辟 16個(gè)字節(jié)
如果sp1是類的成員變量,則在堆空間開辟 16個(gè)字節(jié)
*/
print("sPoint1 sp1 size:\(MemoryLayout.size(ofValue: sp1))")
class cPoint1 {
var x = 10
var y = 30
}
let cp1 = cPoint1()
/**
cp1 的結(jié)構(gòu)
┏━━━━━━━┓
┃ cp1 ┃
┃(指針) ------> 堆空間
┗━━━━━━━┛ ┏━━━━━━━━━━━━━┓
┃ classInfo ┃
┃ retainCount ┃
┃ x(10) ┃
┃ y(30) ┃
┗━━━━━━━━━━━━━┛
這里,cp1是一個(gè)指針,同樣,cp1可能在??臻g、堆空間、全局區(qū)
但是 cp1指向的對(duì)象,一定在堆空間
因此cp1占用8個(gè)字節(jié),cp1指向的對(duì)象占用32個(gè)字節(jié)
*/
print("cPoint1 cp1 size:\(MemoryLayout.size(ofValue: cp1))")
print("cPoint1 cp1 obj size:\(class_getInstanceSize(type(of: cp1)))")
// (3)值類型的賦值(實(shí)際上是深拷貝:Copy On Write)
let sp2 = sp1 // 這里實(shí)際上會(huì)將sp1的內(nèi)存拷貝一份到新的sp2空間
var sp3 = sp1 // 同上
// 不過(guò)在swift標(biāo)準(zhǔn)庫(kù)中,為了提升性能,String、Array、Dictionary、Set等采取了Copy On Write技術(shù)
// 該技術(shù)意思是,只有被拷貝的副本真正需要執(zhí)行寫(修改)操作的時(shí)候,才會(huì)進(jìn)行深拷貝操作
// 不過(guò)該操作只針對(duì)swift標(biāo)準(zhǔn)庫(kù)類型
// 所以在我們不需要修改類型時(shí),盡量使用let定義,這樣編譯器直接不會(huì)進(jìn)行深拷貝操作
// 注意:
var sp4 = sPoint1(x: 1, y: 2)
sp4 = sPoint1(x: 3, y: 5)
/**
sp4 的結(jié)構(gòu)
┏━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━┓
┃0x1000000 x(1) ┃ ------> ┃0x1000000 x(3) ┃
┃0x1000008 y(2) ┃ ┃0x1000008 y(5) ┃
┗━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━┛
//該操作實(shí)際上類似于深拷貝,sp4不會(huì)開辟新空間,而是值覆蓋
*/
// (4)引用類型的賦值(淺拷貝,即拷貝內(nèi)存地址:指針地址)
let cp2 = cp1
// 該操作只會(huì)讓cp2擁有和cp1同樣的指針地址
// 即兩個(gè)指針指向同一個(gè)對(duì)象,雖然cp2擁有cp1相關(guān)信息,但并不擁有獨(dú)立空間
}
test_struct_class()
// 4.let 對(duì)值類型和引用類型的區(qū)別
func test_let_for_struct_class() {
struct Point {
var x = 1
var y = 1
}
class Size {
var x = 1
var y = 1
init(x: Int, y: Int) {
self.x = x
self.y = y
}
}
let p = Point(x: 5, y: 4)
// p.x = 8 // 報(bào)錯(cuò)
let s = Size(x: 5, y: 4)
s.x = 8
/** 對(duì)比可知
對(duì)于let修飾的:
如果是值類型,那么該對(duì)象本身和內(nèi)部成員都不可修改
如果是引用類型,那么指針指向不可修改,但是指向的對(duì)象可以修改
可以粗暴的這樣理解
對(duì)于值類型 p 被 let 修飾,由于p的成員都在let之后,則不可修改
對(duì)于引用類型 s 被 let 修飾,s的在let之后,但s指向的對(duì)象卻在另一個(gè)空間,不歸let管
*/
}
test_let_for_struct_class()
// 5.嵌套類型和方法
func test_nest_func() {
// 嵌套
struct A {
enum A1 {
case a11, a12, a13, a14
}
enum A2: Int {
case a21 = 2, a22, a23, a24
}
}
var a1 = A.A1.a13
a1 = .a14
// 類、結(jié)構(gòu)體、枚舉 都可以定義方法
class Size {
var w = 10
var h = 10
func show(){
print("Size w = \(w), h = \(h)")
}
}
struct Point {
var x = 10
var y = 10
func show(){
print("Point w = \(x), h = \(y)")
}
}
enum TestEnum {
case a1, a2, a3
func show(){
print("A is \(self)")
}
}
let s = Size()
s.show()
let p = Point()
p.show()
let e = TestEnum.a1
e.show()
}
test_nest_func()
認(rèn)識(shí)Swift系列6之結(jié)構(gòu)體和類
?著作權(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ù)。
【社區(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ù)。
相關(guān)閱讀更多精彩內(nèi)容
- ViewModel層,就是View和Model層的粘合劑,他是一個(gè)放置用戶輸入驗(yàn)證邏輯,視圖顯示邏輯,發(fā)起網(wǎng)絡(luò)請(qǐng)求...
- Google Fast Pair正是利用了前面所說(shuō)的LE配對(duì)認(rèn)證后生成的LTK與經(jīng)典藍(lán)牙所需的link key可以...
- 場(chǎng)景設(shè)置 經(jīng)歷了一個(gè)完成的訓(xùn)練營(yíng)的開辦過(guò)程,發(fā)現(xiàn)了一個(gè)特點(diǎn)。大部分訓(xùn)練營(yíng)的學(xué)員來(lái)自于重復(fù)報(bào)名參與線下獲得的學(xué)習(xí)者。...