
一、類(lèi)
Swift類(lèi)是構(gòu)建代碼所用的一種通用且靈活的構(gòu)造體。
我們可以為類(lèi)定義屬性(常量、變量)和方法。
與其他編程語(yǔ)言所不同的是,Swift并不要求你為自定義類(lèi)去創(chuàng)建獨(dú)立的接口和實(shí)現(xiàn)文件。你所要做的是在一個(gè)單一文件中定義一個(gè)類(lèi),系統(tǒng)會(huì)自動(dòng)生成面向其他代碼的外部接口。
類(lèi)和結(jié)構(gòu)體對(duì)比
Swift中類(lèi)和結(jié)構(gòu)體有很多共同點(diǎn)。共同處在于:
1.定義屬性用于存儲(chǔ)值。
2.定義方法用于提供功能。
3.定義附屬腳本用于訪(fǎng)問(wèn)值。
4.定義構(gòu)造器用于生成初始化值。
5.通過(guò)擴(kuò)展以增加默認(rèn)實(shí)現(xiàn)的功能。
6.符合協(xié)議以對(duì)某類(lèi)提供能標(biāo)準(zhǔn)功能。
與結(jié)構(gòu)體相比,類(lèi)還有如下的附加功能:
1.繼承允許一個(gè)類(lèi)繼承另一個(gè)類(lèi)的特征。
2.類(lèi)型轉(zhuǎn)換允許在運(yùn)行時(shí)檢查和解釋一個(gè)類(lèi)實(shí)例的類(lèi)型。
3.解構(gòu)器允許一個(gè)類(lèi)實(shí)例釋放任何其所被分配的資源。
4.引用計(jì)數(shù)器允許對(duì)一個(gè)類(lèi)的多次引用。
語(yǔ)法:
class className {
Definition 1
Definition 2
......
Definition N
}
類(lèi)定義
class student {
var studentName : String
var mark1 : Int
var mark2 : Int
}
實(shí)例化類(lèi):
let studentRecord = student()
實(shí)例:
class MarksStruct {
var mark : Int
init(mark : Int) {
self.mark = mark
}
}
class studentMarks {
var mark = 300
}
let marks = studentMarks()
print("成績(jī)?yōu)閈(marks.mark)")
以上程序的執(zhí)行結(jié)果為:
成績(jī)?yōu)?300
作為引用類(lèi)型訪(fǎng)問(wèn)類(lèi)屬性
類(lèi)屬性可以通過(guò),來(lái)訪(fǎng)問(wèn)。格式為:實(shí)例化類(lèi)名.屬性名:
class MarksStruct {
var mark : Int
init(mark : Int) {
self.mark = mark
}
}
class studentMarks {
var mark1 = 300
var mark2 = 400
var mark3 = 900
}
let marks = studentMarks()
print("Mark is \(marks.mark1)")
print("Mark is \(marks.mark2)")
print("Mark is \(marks.mark3)")
以上程序執(zhí)行輸出結(jié)果:
Mark1 is 300
Mark2 is 400
Mark3 is 900
恒等運(yùn)算符
因?yàn)轭?lèi)是引用類(lèi)型,有可能有多個(gè)常量和變量在后臺(tái)同時(shí)引用某一個(gè)實(shí)例。
為了能夠判斷兩個(gè)常量或者變量是否引用同一個(gè)類(lèi)實(shí)例,Swift內(nèi)建了兩個(gè)恒等運(yùn)算符。

實(shí)例
class SampleClass : EquaTable {
let myProperty : String
init(s : Sting) {
myProperty = s
}
}
func == (lhs: SampleClass, rhs: SampleClass) -> Bool {
return lhs.myProperty == rhs.myProperty
}
let spClass1 = SampleClass(s : "Hello")
let spClass2 = SampleClass(s : "Hello")
if spClass1 === spClass2 {
print("引用相同的類(lèi)實(shí)例\(spClass1)")
}
if spClass1 !== spClass2 {
print("引用不相同的類(lèi)實(shí)例\(spClass2)")
}
以上程序執(zhí)行輸出結(jié)果為:
引用不相同的類(lèi)實(shí)例:SampleClass
二、屬性
Swift屬性將值與特定的類(lèi)、結(jié)構(gòu)或枚舉關(guān)聯(lián)。
屬性可分為存儲(chǔ)屬性和計(jì)算屬性:

存儲(chǔ)屬性和計(jì)算屬性通常用于特定類(lèi)型的實(shí)例。
屬性也可以直接用于類(lèi)型本身,這種屬性稱(chēng)為類(lèi)型屬性。
另外,還可以定義屬性觀(guān)察器來(lái)監(jiān)控屬性值的變化,以此來(lái)觸發(fā)一個(gè)自定義的操作。屬性觀(guān)察器來(lái)監(jiān)控屬性值的變化,以此來(lái)觸發(fā)一個(gè)自定義的操作。屬性觀(guān)察器可以添加到自己寫(xiě)的存儲(chǔ)屬性上,也可以添加到從父類(lèi)繼承的屬性上。
存儲(chǔ)屬性
簡(jiǎn)單來(lái)說(shuō),一個(gè)存儲(chǔ)屬性就是存儲(chǔ)在特定類(lèi)或結(jié)構(gòu)體的實(shí)例里的一個(gè)常量或變量。
存儲(chǔ)屬性可以是變量存儲(chǔ)屬性(用關(guān)鍵字var定義),也可以是常量存儲(chǔ)屬性(用關(guān)鍵字let定義)。
1.可以在定義存儲(chǔ)屬性的時(shí)候指定默認(rèn)值。
2.也可以在構(gòu)造過(guò)程中設(shè)置或修改存儲(chǔ)屬性的值,甚至修改常量存儲(chǔ)屬性的值。
struct Number {
var digits : Int
let pi = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.pi)")
以上程序執(zhí)行輸出結(jié)構(gòu)為:
67
3.1415
考慮一下代碼:
let pi = 3.1415
代碼中pi定義存儲(chǔ)屬性的時(shí)候指定默認(rèn)值(pi = 3.1415),所以不管你什么時(shí)候?qū)嵗Y(jié)構(gòu)體,它都不會(huì)改變。如果你定義的是一個(gè)常量存儲(chǔ)屬性,如果嘗試修改它就會(huì)報(bào)錯(cuò),如下所示:
struct Number {
var digits : Int
let numbers = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7
以上程序執(zhí)行將會(huì)報(bào)錯(cuò),錯(cuò)誤如下所示:
error: cannot assign to property: 'numbers' is a 'let' constant
n.numbers = 8.7
意思為‘numbers’是一個(gè)常量,你不能修改它。
延遲存儲(chǔ)屬性
延遲存儲(chǔ)屬性是指當(dāng)?shù)谝淮伪徽{(diào)用的時(shí)候才會(huì)計(jì)算其初始值的屬性。
在屬性聲明前使用lazy來(lái)標(biāo)示一個(gè)延遲存儲(chǔ)屬性。
注意:
必須將延遲存儲(chǔ)屬性聲明成變量(使用var關(guān)鍵字),因?yàn)閷傩缘闹翟趯?shí)例構(gòu)造完成之前可能無(wú)法得到。而常量屬性在構(gòu)造過(guò)程完成之前必須要有初始值,因此無(wú)法聲明成延遲屬性。
延遲存儲(chǔ)屬性一般用于:
1.延遲對(duì)象的創(chuàng)建。
2.當(dāng)屬性的值依賴(lài)于其他未知類(lèi)
class sample {
lazy var no = number()
}
class number {
var name = "Apple"
}
var firstSample = sample()
print(firstSample.no.name)
以上程序執(zhí)行輸出結(jié)果為:
Apple
實(shí)例化變量
如果您有過(guò)OC經(jīng)驗(yàn),應(yīng)該知道OC為類(lèi)實(shí)例存儲(chǔ)值和引用提供兩種方法。對(duì)于屬性來(lái)說(shuō),也可以使用實(shí)例變量作為屬性值的后端存儲(chǔ)。
Swift編程語(yǔ)言中把這些理論統(tǒng)一用屬性來(lái)實(shí)現(xiàn)。Swift中的屬性沒(méi)有對(duì)應(yīng)的實(shí)例變量,屬性的后端存儲(chǔ)也無(wú)法直接訪(fǎng)問(wèn)。這就避免了不同場(chǎng)景下訪(fǎng)問(wèn)方式的困擾,同時(shí)也將屬性的定義簡(jiǎn)化成一個(gè)語(yǔ)句。
一個(gè)類(lèi)型中屬性的全部信息一一包括命名、類(lèi)型和內(nèi)存管理特征--都在唯一一個(gè)地方(類(lèi)型定義中)定義。
計(jì)算屬性
除存儲(chǔ)屬性外,類(lèi)、結(jié)構(gòu)體和枚舉可以定義計(jì)算屬性,計(jì)算屬性不直接存儲(chǔ)值,而是提供一個(gè)getter來(lái)獲取值,一個(gè)可選的setter來(lái)間接設(shè)置其他屬性或變量。
class sample {
var nol = 0.0, no2 = 0.0
var length = 300.0, breadth = 150.0
var middle: (Double, Double) {
get {
return (length / 2, breadth / 2)
}
set(axis) {
no1 = axis.0 - (length / 2)
no2 = axis.1 - (length / 2)
}
}
}
var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)
print(result.no1)
print(result.no2)
以上程序執(zhí)行輸出結(jié)果為:
(150.0,75.0)
-150.0
-65.0
如果計(jì)算屬性的setter沒(méi)有定義表示新值參數(shù)名,則可以使用默認(rèn)名稱(chēng)newValue。
只讀計(jì)算屬性
只有g(shù)etter沒(méi)有setter的計(jì)算屬性就是只讀計(jì)算屬性。
只讀計(jì)算屬性總是返回一個(gè)值,可以通過(guò)點(diǎn)(.)運(yùn)算符訪(fǎng)問(wèn),單但不能設(shè)置新的值。
class film {
var head = ""
var duration = 0.0
var metaInfo: [String : String] {
return [
"head" : self.head,
"duration" : "\(self,duration)"
]
}
}
var movie = film()
movie.head = "Swift屬性"
movie.duration = 3.09
print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)
以上程序執(zhí)行輸出結(jié)果為:
Swift屬性
3.09
注意:
必須使用var關(guān)鍵字定義計(jì)算屬性,包括只讀計(jì)算屬性,因?yàn)樗鼈兊闹挡皇枪潭ǖ?。let關(guān)鍵字只用來(lái)聲明常量屬性,表示初始化后再也無(wú)法修改的值。
屬性觀(guān)察器
屬性觀(guān)察器監(jiān)控和響應(yīng)屬性值的變化,每次屬性被設(shè)置值的時(shí)候都會(huì)調(diào)用屬性觀(guān)察器,甚至新的值和現(xiàn)在的值相同的時(shí)候也不例外。
可以為除了延遲存儲(chǔ)屬性之外的其他存儲(chǔ)屬性添加屬性觀(guān)察器,也可以通過(guò)重載屬性的方式為繼承的屬性(包括存儲(chǔ)屬性和計(jì)算屬性)添加屬性觀(guān)察器。
注意:
不需要為無(wú)法重載的計(jì)算屬性添加屬性觀(guān)察器,因?yàn)榭梢酝ㄟ^(guò)setter直接監(jiān)控和響應(yīng)值的變化。
可以為屬性添加如下的一個(gè)或全部觀(guān)察器:
1.willSet在設(shè)置新的值之前調(diào)用。
2.didSet在新的值被設(shè)置之后立即調(diào)用。
3.willSet和didSet觀(guān)察器在屬性初始化過(guò)程中不會(huì)被調(diào)用。
class Samplepgm {
var counter : Int = 0 {
willSet(newTotal) {
print("計(jì)數(shù)器:\(newTotal)")
}
didSet {
if counter > oldValue {
print("新增數(shù)\(counter - oldValue)")
}
}
}
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800
以上程序執(zhí)行輸出結(jié)果為:
計(jì)數(shù)器:100
新增數(shù):100
計(jì)數(shù)器:800
新增數(shù):700
全局變量和局部變量
計(jì)算屬性和屬性觀(guān)察器所描述的模式也可以用于全局變量和局部變量。

類(lèi)型屬性
類(lèi)型屬性是作為類(lèi)型定義的一部分寫(xiě)在類(lèi)型最外層的花括號(hào)({})內(nèi)。
使用關(guān)鍵字static來(lái)定義值類(lèi)型的類(lèi)型屬性,關(guān)鍵字class來(lái)為類(lèi)定義類(lèi)型屬性。
struct StructName {
static var storedTypeProperty = " "
static var computedTypeProperty: Int {
//返回一個(gè)Int值
}
}
enum Enumname {
static var storedTypeProperty = ""
static var computedTypeProperty: Int {
//返回一個(gè)Int值
}
}
class Classname {
class var computedTypeProperty: Int {
//返回一個(gè)Int值
}
}
注意:
例子中的計(jì)算型類(lèi)型屬性是只讀的,但也可以定義可讀可寫(xiě)的計(jì)算型類(lèi)型屬性,跟實(shí)例計(jì)算屬性的語(yǔ)法類(lèi)似。
獲取和設(shè)置類(lèi)型屬性的值
類(lèi)似于實(shí)例的屬性,類(lèi)型屬性的訪(fǎng)問(wèn)也是通過(guò)點(diǎn)運(yùn)算符(.)來(lái)進(jìn)行。但是,類(lèi)型屬性是通過(guò)類(lèi)型本身來(lái)獲取和設(shè)置,而不是通過(guò)實(shí)例。實(shí)例如下:
struct StudentMarks {
static let markCount = 97
static var totalCount = 0
var InternalMarks: Int = 0 {
didSet {
if InternalMarks > StudentMarks.markCount {
InternalMarks = StudentMarks.markCount
}
if InternalMarks > StudentMarks.totalCount {
StudentMarks.totalCount = InternalMarks
}
}
}
}
var studentMark1 = StudentMarks()
var studentMark2 = StudentMarks()
student1Mark1.InternalMarks = 98
print(studentMark1 > InternalMarks)
student1Mark2.InternalMarks = 87
print(studentMark2 > InternalMarks)
以上程序執(zhí)行輸出結(jié)果為:
97
87
三、方法
Swift方法是與某些特定類(lèi)型相關(guān)聯(lián)的函數(shù)。
在OC中,類(lèi)唯一能定義方法的類(lèi)型。但在Swift中,你不僅能選擇是否要定義一個(gè)類(lèi)、結(jié)構(gòu)體、枚舉,還能靈活的在你穿件的類(lèi)型(類(lèi)、結(jié)構(gòu)體、枚舉)上定義方法。
實(shí)例方法
在Swift語(yǔ)言中,實(shí)例方法是屬于某個(gè)特定類(lèi)、結(jié)構(gòu)體或者枚舉類(lèi)型實(shí)例的方法。
實(shí)例方法提供以下方法:
1.可以訪(fǎng)問(wèn)和修改實(shí)例屬性。
2.提供與實(shí)例目的相關(guān)的功能。
實(shí)例方法
在Swift語(yǔ)言中,實(shí)例方法是屬于繆戈特定類(lèi)、結(jié)構(gòu)體或者枚舉類(lèi)型實(shí)例的方法。
實(shí)例方法提供以下方法:
1.可以訪(fǎng)問(wèn)和修改實(shí)例屬性。
2.提供與實(shí)例目的相關(guān)的功能。
實(shí)例方法要寫(xiě)在它所屬的類(lèi)型的前后大括號(hào)({})之間。
實(shí)例方法能夠隱式訪(fǎng)問(wèn)它所屬類(lèi)型的所有的其他實(shí)例方法和屬性。
實(shí)例方法只能被它所屬的類(lèi)的某個(gè)特定實(shí)例調(diào)用。
實(shí)例方法不能脫離于現(xiàn)存的實(shí)例而被調(diào)用。
語(yǔ)法:
func funcName(Parameters) -> returnType {
Statement1
Statement2
......
StatementN
return parameters
}
實(shí)例:
class Counter {
var count = 0
func increment() {
count += 1
}
func incrementBy(amount: Int) {
count += amount
}
func reset() {
count = 0
}
}
//初始計(jì)數(shù)值是0
let counter = Counter()
//計(jì)數(shù)值現(xiàn)在是1
counter.increment()
//計(jì)數(shù)值現(xiàn)在是6
counter.incrementBy(amount : 5)
print(counter.count)
//計(jì)數(shù)值現(xiàn)在是0
counter.reset()
print(counter.count)
以上程序的執(zhí)行結(jié)果為:
6
0
Counter類(lèi)定義了三個(gè)實(shí)例方法:
1.increment讓計(jì)數(shù)器按1遞增。
2.incrementBy(amount : Int)讓計(jì)數(shù)器按一個(gè)指定的整數(shù)值遞增。
3.reset將計(jì)數(shù)器重置為0。
Counter這個(gè)類(lèi)還聲明了一個(gè)可變屬性count,用它來(lái)保持對(duì)當(dāng)前計(jì)數(shù)器值的追蹤。
方法的局部參數(shù)名稱(chēng)和外部參數(shù)名稱(chēng)
Swift函數(shù)參數(shù)可以同時(shí)有一個(gè)局部名稱(chēng)(在函數(shù)體內(nèi)部使用)和一個(gè)外部名稱(chēng)(在調(diào)用函數(shù)時(shí)使用Swift中的方法和OC中的方法極其相似。像在OC中一樣,Swift中方法的名稱(chēng)通常用一個(gè)介詞指向方法的第一個(gè)參數(shù),比如:with、for、by等等)。
Swift默認(rèn)僅給方法的第一個(gè)參數(shù)名稱(chēng)一個(gè)局部參數(shù)名稱(chēng),默認(rèn)同時(shí)給第二個(gè)和后續(xù)參數(shù)名稱(chēng)全局參數(shù)名稱(chēng)。
以下實(shí)例中‘no1’在Swift中聲明為局部參數(shù)名稱(chēng)?!畁o2’用于全局的聲明并通過(guò)外部程序訪(fǎng)問(wèn)。
class division {
var count: Int = 0
func incrementBy(no1: Int, no2: Int) {
count = no1 / no2
print(count)
}
}
let counter = division()
counter.incrementBy(no1: 1800, no2: 3)
counter.incrementBy(no1: 1900, no2: 2)
counter.incrementBy(no1: 11100, no2: 2)
以上程序執(zhí)行的輸出結(jié)果為:
600
950
5550
是否提供外部名稱(chēng)設(shè)置
我們強(qiáng)制在第一個(gè)參數(shù)添加外部名稱(chēng)把這個(gè)局部名稱(chēng)當(dāng)做外部名稱(chēng)使用(Swift2.0前是使用#號(hào))。
相反,我們呢也可以使用下劃線(xiàn)(_)設(shè)置第二個(gè)及后續(xù)的參數(shù)不提供一個(gè)外部名稱(chēng)。
class multiplication {
var count: Int = 0
func incrementBy(first no1: Int, no2: Int) {
count = no1 * no2
print(count)
}
}
let counter = multipication()
counter.incrementBy(first: 800, no2: 3)
counter.incrementBy(first: 100, no2: 5)
counter.incrementBy(first: 15000, no2: 3)
以上程序執(zhí)行輸出結(jié)果為:
2400
500
45000
Self屬性
類(lèi)型的每一個(gè)實(shí)例都有一個(gè)隱含屬性叫做self,self完全等同于該實(shí)例本身。
你可以在一個(gè)實(shí)例的實(shí)例方法中使用這個(gè)隱含的self屬性來(lái)引用當(dāng)前實(shí)例。
class calculations {
let a : Int
let b : Int
let res : Int
init(a: Int, b: Int) {
self.a = a
self.b = b
res = a+b
print("Self 內(nèi):\(res)")
}
func tot(c : Int) -> Int {
return res - c
}
func result() {
print("結(jié)果為:\(tot(c : 20))")
print("結(jié)果為:\(tot(c : 50))")
}
}
let pri = calculations(a: 600, b: 300)
let sum = calculations(a: 1200, b: 300)
pri.result()
sum.result()
以上程序執(zhí)行輸出結(jié)果為:
Self內(nèi):900
Self內(nèi):1500
結(jié)果為:880
結(jié)果為:850
結(jié)果為:1480
結(jié)果為:1450
在實(shí)例方法中修改值類(lèi)型
Swift語(yǔ)言中結(jié)構(gòu)體和枚舉是值類(lèi)型。一般情況下,值類(lèi)型的屬性不能在它的實(shí)例方法中被修改。
但是,如果你確實(shí)需要在某個(gè)具體的方法中修改結(jié)構(gòu)體或者枚舉的屬性,你可以選擇變異(mutating)這個(gè)方法,然后方法就可以從方法內(nèi)部改變它的屬性;并且它做的任何改變?cè)诜椒ńY(jié)束時(shí)還會(huì)保留在原始結(jié)構(gòu)中。
方法還可以給它隱含得到self屬性賦值一個(gè)全新的實(shí)例,這個(gè)新實(shí)例在方法結(jié)束后將替換原來(lái)的實(shí)例。
struct area {
var length = 1
var breadth = 1
func area() -> Int {
return length * breadth
}
mutating func scaleBy(res: Int) {
length *= res
breadth *= res
print(length)
print(breadth)
}
}
var val = area(length: 3, breadth: 5)
var.scaleBy(res: 3)
var.scaleBy(res: 30)
var.scaleBy(res: 300)
以上程序執(zhí)行輸出結(jié)果為:
9
15
270
450
81000
135000
在可變方法中給self賦值
可變方法能夠賦給隱含屬性self一個(gè)全新的實(shí)例。
struct area {
var length = 1
var breadth = 1
func area() -> Int {
return length * breadth
}
mutating func scaleBy(res: Int) {
self.length *= res
self.breadth *= res
print(length)
print(breadth)
}
}
var val = area(length: 3, breadth: 5)
var.scaleBy(res: 13)
以上程序執(zhí)行輸出結(jié)果為:
39
65
類(lèi)型方法
實(shí)例方法是被類(lèi)型的某個(gè)實(shí)例調(diào)用的方法,你也可以定義類(lèi)型本身調(diào)用的方法,這種方法就叫做類(lèi)型方法。
聲明結(jié)構(gòu)體和枚舉的類(lèi)型方法,在方法的func關(guān)鍵字之前加上關(guān)鍵字static。類(lèi)可能會(huì)用關(guān)鍵字class來(lái)允許子類(lèi)重寫(xiě)父類(lèi)的實(shí)現(xiàn)方法。
類(lèi)型方法和實(shí)例方法一樣用點(diǎn)號(hào)(.)語(yǔ)法調(diào)用。
class Math {
class func abs(number: Int) -> Int {
if number < 0 {
return (-number)
} else {
return number
}
}
}
struct absno {
static func abs(number : Int) -> Int {
if number< 0 {
return (-number)
} else {
return number
}
}
}
let no = Math.abs(number: -35)
let num = absno.abs(number: -5)
print(no)
print(num)
以上程序執(zhí)行輸出結(jié)果為:
35
5