Swift - 類(lèi)、屬性、方法

一、類(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

下一篇:“Swift - 繼承” http://www.itdecent.cn/p/39b5348f1f1b

最后編輯于
?著作權(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)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容