Swift基礎-結(jié)構撇他、屬性和方法

創(chuàng)建自己的結(jié)構

Swift可讓您通過兩種方式設計自己的類型,其中最常見的稱為結(jié)構狈蚤,或簡稱為structs困肩。可以給結(jié)構賦予它們自己的變量和常量以及它們自己的功能炫惩,然后根據(jù)需要創(chuàng)建和使用它們僻弹。

讓我們從一個簡單的示例開始:我們將創(chuàng)建一個Sport將其名稱存儲為字符串的結(jié)構。結(jié)構內(nèi)部的變量稱為properties他嚷,因此這是具有一個屬性的結(jié)構:

struct Sport {
    var name: String
}

定義了類型蹋绽,因此現(xiàn)在我們可以創(chuàng)建和使用它的實例:

var tennis = Sport(name: "Tennis")
print(tennis.name)

我們制作了nametennis變量,因此可以像常規(guī)變量一樣更改它們:

tennis.name = "Lawn tennis"

屬性可以像常規(guī)變量一樣具有默認值筋蓖,并且通承对牛可以依靠Swift的類型推斷。

計算屬性

我們只是創(chuàng)建了一個Sport這樣的結(jié)構:

struct Sport {
    var name: String
}

具有存儲一個String的屬性name粘咖。這些稱為存儲屬性蚣抗,因為Swift具有另一種稱為計算屬性的屬性-一種運行代碼以計算其值的屬性。

我們將向該Sport結(jié)構添加另一個存儲的屬性瓮下,然后是一個計算的屬性翰铡。看起來是這樣的:

struct Sport {
    var name: String
    var isOlympicSport: Bool

    var olympicStatus: String {
        if isOlympicSport {
            return "\(name) is an Olympic sport"
        } else {
            return "\(name) is not an Olympic sport"
        }
    }
}

如您所見讽坏,它olympicStatus看起來像一個普通的String锭魔,但是它會根據(jù)其他屬性返回不同的值辛臊。

我們可以通過創(chuàng)建一個新實例Sport來進行嘗試:

let chessBoxing = Sport(name: "Chessboxing", isOlympicSport: false)
print(chessBoxing.olympicStatus)

let gameBoxing = Sport(name: "gameBoxing", isOlympicSport: true)
print(gameBoxing.olympicStatus)

輸出內(nèi)容如下:

Chessboxing is not an Olympic sport
gameBoxing is an Olympic sport

屬性觀察器

通過屬性觀察器劈彪,可以在任何屬性更改之前或之后運行代碼邪乍。為了說明這一點,我們將編寫一個Progress跟蹤任務和完成百分比的結(jié)構:

struct Progress {
    var task: String
    var amount: Int
}

現(xiàn)在硬霍,我們可以創(chuàng)建該結(jié)構的實例并隨時間調(diào)整其進度:

var progress = Progress(task: "Loading data", amount: 0)
progress.amount = 30
progress.amount = 80
progress.amount = 100

我們想讓 Swift每次amount更改時都打印一條消息碱妆,我們可以使用didSet屬性觀察器懈息。每次amount更改時罕扎,它將運行一些代碼:

struct Progress {
    var task: String
    var amount: Int {
        didSet {
            print("\(task) is now \(amount)% complete")
        }
    }
}

您還可以willSet用來在屬性更改之前采取措施,但這很少使用庆锦。

方法

結(jié)構內(nèi)部可以具有函數(shù)捅位,并且這些函數(shù)可以根據(jù)需要使用結(jié)構的屬性。結(jié)構內(nèi)部的函數(shù)稱為方法肥荔,但它們?nèi)允褂孟嗤?code>func關鍵字绿渣。

我們可以用一個City結(jié)構來證明這一點。這將具有一個population存儲城市人口的屬性燕耿,以及一個collectTaxes()返回人口乘以1000的方法中符。由于該方法屬于City,因此可以讀取當前城市的population屬性誉帅。

這是代碼:

struct City {
    var population: Int

    func collectTaxes() -> Int {
        return population * 1000
    }
}

該方法屬于該結(jié)構淀散,因此我們在該結(jié)構的實例上調(diào)用它,如下所示:

let london = City(population: 9_000_000)
london.collectTaxes()

變異方法

如果一個結(jié)構具有可變屬性蚜锨,但是該結(jié)構的實例被創(chuàng)建為常量档插,則該屬性不能更改–該結(jié)構是恒定的,因此亚再,無論如何創(chuàng)建郭膛,其所有屬性也是恒定的。

問題在于氛悬,當您創(chuàng)建結(jié)構時则剃,Swift不知道是否將其與常量或變量一起使用,因此默認情況下采用安全方法:除非明確要求如捅,否則Swift不會允許您編寫更改屬性的方法棍现。

當您想在方法內(nèi)部更改屬性時,需要使用mutating關鍵字對其進行標記镜遣,如下所示:

struct Person {
    var name: String

    mutating func makeAnonymous() {
        name = "Anonymous"
    }
}

因為它更改了屬性己肮,所以Swift僅允許在Person作為變量的實例上調(diào)用該方法:

var person = Person(name: "Ed")
person.makeAnonymous()

字符串的屬性和方法

到目前為止,我們已經(jīng)使用了很多字符串悲关,事實證明它們是結(jié)構-它們具有自己的方法和屬性谎僻,可用于查詢和操作字符串。

首先寓辱,讓我們創(chuàng)建一個測試字符串:

let string = "Do or do not, there is no try."

您可以使用其count屬性讀取字符串中的字符數(shù):

print(string.count)

他們有一個hasPrefix()方法艘绍,如果字符串以特定字母開頭,則返回true

print(string.hasPrefix("Do"))

您可以通過調(diào)用字符串的uppercased()方法將其大寫:

print(string.uppercased())

您甚至可以讓Swift將字符串的字母排序成一個數(shù)組:

print(string.sorted())

字符串具有更多的屬性和方法-嘗試鍵入string.以顯示Xcode的代碼完成選項讶舰。

數(shù)組的屬性和方法

數(shù)組也是結(jié)構,這意味著它們也具有自己的方法和屬性,可用于查詢和操作數(shù)組跳昼。

這是一個讓我們開始的簡單數(shù)組:

var toys = ["Woody"]

您可以使用其count屬性讀取數(shù)組中的項目數(shù):

print(toys.count)

如果要添加新項目般甲,請使用如下append()方法:

toys.append("Buzz")

您可以使用其firstIndex()方法在數(shù)組內(nèi)找到任何項,如下所示:

toys.firstIndex(of: "Buzz")

這將返回1鹅颊,因為數(shù)組從0開始計數(shù)敷存。

就像使用字符串一樣,您可以讓Swift將數(shù)組的項目按字母順序排序:

print(toys.sorted())

最后堪伍,如果要刪除項目锚烦,請使用如下remove()方法:

toys.remove(at: 0)

數(shù)組具有更多的屬性和方法–嘗試鍵入toys.以顯示Xcode的代碼完成選項。

初始化器

初始化器是特殊的方法帝雇,提供不同的方法來創(chuàng)建結(jié)構涮俄。默認情況下,所有結(jié)構都帶有一個名為成員級初始值設定項的值尸闸,這要求您在創(chuàng)建結(jié)構時為每個屬性提供一個值彻亲。

如果我們創(chuàng)建User具有一個屬性的結(jié)構,則可以看到以下內(nèi)容:

struct User {
    var username: String
}

創(chuàng)建這些結(jié)構之一時吮廉,必須提供用戶名:

var user = User(username: "twostraws")

我們可以提供自己的初始化程序來替換默認的初始化程序苞尝。例如,我們可能希望將所有新用戶創(chuàng)建為“匿名”并打印一條消息宦芦,如下所示:

struct User {
    var username: String

    init() {
        username = "Anonymous"
        print("Creating a new user!")
    }
}

你不寫func初始化之前宙址,但是你做的必要,以確保所有屬性都初始化結(jié)束前的值调卑。

現(xiàn)在我們的初始化程序不接受任何參數(shù)抡砂,我們需要創(chuàng)建如下結(jié)構:

var user = User()
user.username = "twostraws"

引用當前實例

在方法內(nèi)部,您會得到一個稱為的特殊常量self令野,該常量指向當前正在使用的結(jié)構的任何實例舀患。當您創(chuàng)建與屬性具有相同參數(shù)名的初始值設定項時,此self值特別有用气破。聊浅。

例如,如果您創(chuàng)建一個Person帶有name屬性的結(jié)構现使,然后嘗試編寫一個接受name參數(shù)的初始化程序低匙,則self可以幫助您區(qū)分屬性和參數(shù)– self.name引用屬性,而name引用參數(shù)碳锈。

這就是代碼中的內(nèi)容:

struct Person {
    var name: String

    init(name: String) {
        print("\(name) was born!")
        self.name = name
    }
}

惰性屬性

作為性能優(yōu)化顽冶,Swift使您僅在需要時才創(chuàng)建一些屬性。舉個例子售碳,考慮一下這個FamilyTree結(jié)構-它并沒有做很多强重,但是從理論上講绞呈,為某人創(chuàng)建家譜需要很長時間:

struct FamilyTree {
    init() {
        print("Creating family tree!")
    }
}

我們可以將該FamilyTree結(jié)構用作Person結(jié)構內(nèi)部的屬性,如下所示:

struct Person {
    var name: String
    var familyTree = FamilyTree()

    init(name: String) {
        self.name = name
    }
}

var ed = Person(name: "Ed")

但是间景,如果我們不總是需要特定人的家譜怎么辦佃声?如果將lazy關鍵字添加到familyTree屬性,則Swift僅在FamilyTree首次訪問該結(jié)構時才會創(chuàng)建該結(jié)構:

lazy var familyTree = FamilyTree()

因此倘要,如果您想看到“正在創(chuàng)建家譜圾亏!”消息,則需要至少訪問一次該屬性:

ed.familyTree

靜態(tài)特性和方法

到目前為止封拧,我們創(chuàng)建的所有屬性和方法都屬于struct的各個實例志鹃,這意味著,如果我們有一個Studentstruct泽西,我們可以創(chuàng)建多個學生實例曹铃,每個實例都具有各自的屬性和方法:

struct Student {
    var name: String

    init(name: String) {
        self.name = name
    }
}

let ed = Student(name: "Ed")
let taylor = Student(name: "Taylor")

您也可以通過將Swift聲明為static來要求Swift在該結(jié)構的所有實例之間共享特定的屬性和方法。

為了嘗試這一點尝苇,我們將向該Student結(jié)構添加一個靜態(tài)屬性铛只,以存儲該班級中有多少學生。每次創(chuàng)建新學生時糠溜,我們都會向其中添加一個:

struct Student {
    static var classSize = 0
    var name: String

    init(name: String) {
        self.name = name
        Student.classSize += 1
    }
}

因為該classSize結(jié)構屬于該結(jié)構本身而不是該結(jié)構的實例淳玩,所以我們需要使用讀取它Student.classSize

print(Student.classSize)

訪問控制

訪問控制允許您限制哪些代碼可以使用屬性和方法。這一點很重要非竿,例如您可能希望阻止人們直接讀取屬性蜕着。

我們可以創(chuàng)建一個Person具有id屬性以存儲其社會保險號的結(jié)構:

struct Person {
    var id: String

    init(id: String) {
        self.id = id
    }
}

let ed = Person(id: "12345")

創(chuàng)建該人后,我們可以將其id設為私有红柱,因此您無法從結(jié)構外部讀取它-嘗試編寫ed.id根本行不通承匣。

只需使用private關鍵字,如下所示:

struct Person {
    private var id: String

    init(id: String) {
        self.id = id
    }
}

現(xiàn)在锤悄,只有內(nèi)部的方法Person可以讀取id屬性韧骗。例如:

struct Person {
    private var id: String

    init(id: String) {
        self.id = id
    }

    func identify() -> String {
        return "My social security number is \(id)"
    }
}

另一個常見的選擇是public,它允許所有其他代碼使用屬性或方法零聚。

總結(jié)

  • 1.您可以使用結(jié)構創(chuàng)建自己的類型袍暴,這些結(jié)構可以具有自己的屬性和方法。
  • 2.您可以使用存儲的屬性或使用計算的屬性即時計算值隶症。
  • 3.如果要更改方法內(nèi)的屬性政模,則必須將其標記為mutating
  • 4.初始化程序是創(chuàng)建結(jié)構的特殊方法蚂会。默認情況下淋样,您將獲得一個成員初始化器,但是如果創(chuàng)建自己的初始化器胁住,則必須為所有屬性賦予一個值趁猴。
  • 5.使用self常量來引用方法內(nèi)部結(jié)構的當前實例刊咳。
  • 6.lazy關鍵字告訴Swift當?shù)谝淮问褂茫麄冎荒軇?chuàng)建屬性儡司。
  • 7.您可以使用static關鍵字在結(jié)構的所有實例之間共享屬性和方法芦缰。
  • 8.訪問控制使您可以限制可以使用屬性和方法的代碼。
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末枫慷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子浪规,更是在濱河造成了極大的恐慌或听,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笋婿,死亡現(xiàn)場離奇詭異誉裆,居然都是意外死亡,警方通過查閱死者的電腦和手機缸濒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門足丢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人庇配,你說我怎么就攤上這事斩跌。” “怎么了捞慌?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵耀鸦,是天一觀的道長。 經(jīng)常有香客問我啸澡,道長袖订,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任嗅虏,我火速辦了婚禮洛姑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘皮服。我一直安慰自己楞艾,他們只是感情好,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布冰更。 她就那樣靜靜地躺著产徊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蜀细。 梳的紋絲不亂的頭發(fā)上舟铜,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音奠衔,去河邊找鬼谆刨。 笑死塘娶,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的痊夭。 我是一名探鬼主播刁岸,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼她我!你這毒婦竟也來了虹曙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤番舆,失蹤者是張志新(化名)和其女友劉穎酝碳,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恨狈,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡疏哗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了禾怠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片返奉。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吗氏,靈堂內(nèi)的尸體忽然破棺而出芽偏,到底是詐尸還是另有隱情,我是刑警寧澤弦讽,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布哮针,位于F島的核電站,受9級特大地震影響坦袍,放射性物質(zhì)發(fā)生泄漏十厢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一捂齐、第九天 我趴在偏房一處隱蔽的房頂上張望蛮放。 院中可真熱鬧,春花似錦奠宜、人聲如沸包颁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽娩嚼。三九已至,卻和暖如春滴肿,著一層夾襖步出監(jiān)牢的瞬間岳悟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留贵少,地道東北人呵俏。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像滔灶,于是被迫代替她去往敵國和親普碎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容