在面向過(guò)程的編程語(yǔ)言(如C語(yǔ)言)中,結(jié)構(gòu)體用得比較多押框,但是面向?qū)ο笾蟛沓瘢缭贑++和OC中,結(jié)構(gòu)體已經(jīng)很少使用了橡伞。這是因?yàn)榻Y(jié)構(gòu)體能夠做的事情盒揉,類(lèi)完全可以取而代之。
而Swift語(yǔ)言卻非常重視結(jié)構(gòu)體兑徘,把結(jié)構(gòu)體作為實(shí)現(xiàn)面向?qū)ο蟮闹匾侄胃沼wift中的結(jié)構(gòu)體與C++和OC中的結(jié)構(gòu)體有很大的差別,C++和OC中的結(jié)構(gòu)體只能定義一組相關(guān)的成員變量挂脑,而Swift中的結(jié)構(gòu)體不僅可以定義屬性藕漱,還可以定義方法。因此崭闲,我們可以把Swfit結(jié)構(gòu)體看做是一種輕量級(jí)的類(lèi)肋联。
Swift中類(lèi)和結(jié)構(gòu)體的共同處在于:
- 定義屬性用于存儲(chǔ)值
- 定義方法用于提供功能
- 定義下標(biāo)腳本用于訪問(wèn)值
- 定義構(gòu)造器用于生成初始化值
- 通過(guò)擴(kuò)展以增加默認(rèn)實(shí)現(xiàn)的功能
- 實(shí)現(xiàn)協(xié)議以提供某種標(biāo)準(zhǔn)功能
Swift中類(lèi)和結(jié)構(gòu)體的不同處在于:
- 結(jié)構(gòu)體不具有繼承性
- 結(jié)構(gòu)體不具備運(yùn)行時(shí)強(qiáng)制類(lèi)型轉(zhuǎn)換
- 結(jié)構(gòu)體不具備使用析構(gòu)器的能力
- 結(jié)構(gòu)體不具備使用引用計(jì)數(shù)的能力
結(jié)構(gòu)體定義
// 結(jié)構(gòu)體定義使用struct關(guān)鍵字
struct MarkStruct {
// 結(jié)構(gòu)體也有存儲(chǔ)屬性和計(jì)算屬性,這里只定義了存儲(chǔ)屬性
var mark1: Int
var mark2: Int
var mark3: Int
}
// 所有結(jié)構(gòu)體都有一個(gè)自動(dòng)生成的成員逐一初始化構(gòu)造器,用于初始化結(jié)構(gòu)體實(shí)例中成員的屬性
// 順序必須和結(jié)構(gòu)體成員順序一致,必須包含所有的成員
var marks = MarkStruct(mark1: 98, mark2: 96, mark3: 100)
print(marks.mark1) // return:98
print(marks.mark2) // return:96
print(marks.mark3) // return:100
結(jié)構(gòu)體定義屬性
// 結(jié)構(gòu)體定義屬性
struct Point {
var x = 0.0
var y = 0.0
}
struct MyPoint {
// 定義存儲(chǔ)屬性
var p = Point()
// 定義計(jì)算屬性
var point:Point {
get {
return p
}
set(newPoint) { // 修改newValue名為newPoint,本質(zhì)還是newValue
p.x = newPoint.x
p.y = newPoint.y
}
}
}
var p = Point(x: 10.0, y: 11.0)
var myPoint = MyPoint()
myPoint.point = p
print("x=\(myPoint.point.x),y=\(myPoint.point.y)") // return:x=10.0,y=11.0
結(jié)構(gòu)體的方法
// 結(jié)構(gòu)體的方法
// 結(jié)構(gòu)體內(nèi)部只有在構(gòu)造函數(shù)(init)中可以修改屬性的值,其他方法內(nèi)不能直接修改結(jié)構(gòu)體內(nèi)部屬性的值。
struct Rect {
var width:Double
var height:Double = 0.0
// 給結(jié)構(gòu)體定義一個(gè)方法, 該方法屬于該結(jié)構(gòu)體
// 結(jié)構(gòu)體中的成員方法必須使用某個(gè)實(shí)例調(diào)用
// 成員方法可以訪問(wèn)成員屬性
func getWidth() -> Double {
return width
}
}
var rect = Rect(width: 10.0, height: 20.0)
// 結(jié)構(gòu)體中的成員方法是和某個(gè)實(shí)例對(duì)象綁定在一起的, 所以誰(shuí)調(diào)用, 方法中訪問(wèn)的屬性就屬于誰(shuí)
print(rect.getWidth()) // return :10.0
var rect2 = Rect(width: 30.0, height: 20.0)
// 取得rect2這個(gè)對(duì)象的寬度
print(rect2.getWidth()) // retrun: 30.0
值類(lèi)型和引用類(lèi)型
值類(lèi)型被賦予給一個(gè)變量刁俭、常數(shù)或者本身被傳遞給一個(gè)函數(shù)的時(shí)候橄仍,實(shí)際上操作的是值的拷貝。
實(shí)際上牍戚,在Swift中侮繁,所有的基本類(lèi)型:整數(shù)、浮點(diǎn)數(shù)如孝、布爾值宪哩、字符串、數(shù)組和字典暑竟,都是值類(lèi)型,并且都是以結(jié)構(gòu)體的形式在后臺(tái)所實(shí)現(xiàn)育勺。
在Swift中但荤,所有的結(jié)構(gòu)體和枚舉都是值類(lèi)型。這意味著它們的實(shí)例涧至,以及實(shí)例中所包含的任何值類(lèi)型屬性腹躁,在代碼中傳遞的時(shí)候都會(huì)被復(fù)制。
值類(lèi)型賦值
struct ReSolution {
var width = 0
var height = 0
}
// 創(chuàng)建一個(gè)結(jié)構(gòu)體
let hd = ReSolution(width: 1920, height: 1080)
// 結(jié)構(gòu)體賦值,實(shí)際上做的是拷貝操作,cinema和hd結(jié)構(gòu)體在內(nèi)存中各自占用獨(dú)立的空間
var cinema = hd
// 修改cinema結(jié)構(gòu)體,不會(huì)影響hd結(jié)構(gòu)體
cinema.width = 2048
print("cinema is now \(cinema.width) pixels wide") // return:2048
print("hd is still \(hd.width) pixels wide") // return:1920
引用類(lèi)型賦值
與值類(lèi)型不同南蓬,引用類(lèi)型在被賦予到一個(gè)變量纺非、常量或者被傳遞到一個(gè)函數(shù)時(shí)哑了,操作的并不是其拷貝。因此烧颖,引用的是已存在的實(shí)例本身而不是其拷貝弱左。
類(lèi)就是引用類(lèi)型。
class ResolutionClass {
var width = 0
var height = 0
init(width: Int,height: Int) {
self.width = width
self.height = height
}
}
// 創(chuàng)建一個(gè)類(lèi)對(duì)象
let hdClass = ResolutionClass(width: 1920, height: 1080)
// 類(lèi)對(duì)象賦值,引用同一個(gè)內(nèi)存空間
var cinemaClass = hdClass
// 修改cinema對(duì)象,本質(zhì)上也是修改hdClass對(duì)象
cinemaClass.width = 2048
print("cinemaClass is now \(cinemaClass.width) pixels wide") // return:2048
print("hdClass is also \(hdClass.width) pixels wide") // return:2048
類(lèi)和結(jié)構(gòu)體的選擇
結(jié)構(gòu)體實(shí)例總是通過(guò)值傳遞炕淮,類(lèi)實(shí)例總是通過(guò)引用傳遞拆火。這意味兩者適用不同的任務(wù)。當(dāng)你的在考慮一個(gè)工程項(xiàng)目的數(shù)據(jù)構(gòu)造和功能的時(shí)候涂圆,你需要決定每個(gè)數(shù)據(jù)構(gòu)造是定義成類(lèi)還是結(jié)構(gòu)體们镜。
當(dāng)符合一條或多條以下條件時(shí),請(qǐng)考慮構(gòu)建結(jié)構(gòu)體:
- 結(jié)構(gòu)體的主要目的是用來(lái)封裝少量相關(guān)簡(jiǎn)單數(shù)據(jù)值润歉。
- 有理由預(yù)計(jì)一個(gè)結(jié)構(gòu)體實(shí)例在賦值或傳遞時(shí)模狭,封裝的數(shù)據(jù)將會(huì)被拷貝而不是被引用。
- 任何在結(jié)構(gòu)體中儲(chǔ)存的值類(lèi)型屬性踩衩,也將會(huì)被拷貝嚼鹉,而不是被引用。
- 結(jié)構(gòu)體不需要去繼承另一個(gè)已存在類(lèi)型的屬性或者行為九妈。
合適的結(jié)構(gòu)體候選者包括: - 幾何形狀的大小
- 一定范圍內(nèi)的路徑
- 三維坐標(biāo)系內(nèi)一點(diǎn)