1. 程式人生 > >12.Swift 中的關鍵字詳解

12.Swift 中的關鍵字詳解

在Swift 中, 不像Objective-C一樣, 有些關鍵字可以找到對應的解釋, 這裡我就列一下常用的關鍵字詳解, 陸續會有增加.

1.let關鍵字

用let修飾的變數會是一個不可變的常量, 也就是說不可以對它進行修改, 但如果用let修飾的常量是一個類, 那麼我們可以對其所在的屬性進行修改, 比如:

class PersonInfo {
    let name = "xiaoming"
    var age = 18
    var height = 170
    var weight = 65
}

let personInfo = PersonInfo()

personInfo.age += 1
print("person age is \(personInfo.age).") // 輸出的結果為: person age is 19.

這裡邊的name就是不可變的, 如果非要去改變, Xcode會建議你把let修改成var.

PS: 如果這個時候, 再宣告一個person常量去引用personInfo, 那麼person的所指向的記憶體塊是和personInfo相同的.

2.var關鍵字

用var關鍵字宣告的變數將會是一個可變的變數, 在這裡, 我們並不會用var去引用一個類, 也沒有必要, 繼續拿上面的例子來說:

class PersonInfo {
    let
name = "xiaoming" var age = 18 var height = 170 var weight = 65 } let personInfo = PersonInfo() personInfo.age += 1 print("person age is \(personInfo.age).")

這裡面的age就是屬於var型別, 在初始化之後, 我們仍然可以給它進行修改.

PS: 如果這個時候, 我們用var修飾personMode變數去引用personInfo, 那麼personMode和personInfo所指向的記憶體塊並不同, personMode會將personInfo完整的拷貝一份, 然後放在另外一塊記憶體塊去管理.

3.class關鍵字

在Swift當中, 我們是使用Class關鍵字去宣告一個類, 比如:

class PersonInfo {
    // class body
}

4.struct關鍵字

在Swift中, 如果我們需要宣告一個結構體, 我們就需要使用到struct關鍵字, 比如:

struct PersonInfo {
    // struct body
}

5.enum關鍵字

而我們需要宣告列舉的時候, 我們就使用enum關鍵字, 比如:

enum PersonMode {
    case zhangsan
    case lisi
    case wangwu(String)
    case luoliu(String, Double, Int)
}

在Swift當中的enum和Objective-C並不一樣, Swift的enum不會被隱式賦值為0, 1, 裡面的zhangsan就是這個列舉分支的完整值, 並且在Swift中, 我們可以給enum case宣告各種型別, 比如裡面的case luoliu一樣.

當然, 我們也可以給列舉值預設宣告一個值, 但在列舉名之前, 要宣告是什麼型別, 比如:

enum Numbers: Int {
    case One = 1, Two, Three, Four
}

let number = Numbers.One.rawValue

print(number)

6.override關鍵字

在Swift中, 如果我們要重寫某個方法, 或者某個屬性的話, 我們需要在重寫的變數前增加一個override關鍵字, 比如:

class Car {
    var speed: Int {
        return 200
    }

    func carSpeed() {
        print("Car max speed is \(speed)km 1 hours.")
    }
}

class NewCar: Car {
    override var speed: Int {
        return 150
    }

    override func carSpeed() {
        print("Car max speed is \(speed)km 1 hours.")
    }
}

7.final關鍵字

上面我們介紹了override重寫屬性或者方法的關鍵字, 當然有重寫, 肯定會有防止重寫的關鍵字, 比如:

class Car {
    var speed: Int {
        return 200
    }

    final var carType: String {
        return "SUV"
    }

    func carSpeed() {
        print("Car max speed is \(speed)km 1 hours.")
    }
}

class NewCar: Car {
    override var speed: Int {
        return 150
    }

    override func carSpeed() {
        print("Car max speed is \(speed)km 1 hours.")
    }

    override var carType: String {
        return "MPV"
    }
}

// 這個時候, 下面這個override var carType: String{}屬性就會報Var override a "final" var 的錯誤.

8.subscript關鍵字

所謂的下標, 其實就可以快捷方式的設定或者獲取對應的屬性, 而不需要呼叫對應的方法去獲取或者儲存, 比如:

struct Animal {
    let catType: String

    subscript(animalName: String) -> String {
        return "catType is \(animalName)."
    }
}

let tiger = Animal(catType: "Tiger")

print(tiger)
// 輸出的結果為: Animal(catType: "Tiger")

9.mutating關鍵字

mutating這個關鍵字指的是可變, 只能用在struct和enum當中, 為的就是可以方便我們在特定環境下, 需要在struct中修改對應的屬性值, 比如:

struct Animal {
    let catType: String

    subscript(animalName: String) -> String {
        return "catType is \(animalName)."
    }
}

let tiger = Animal(catType: "Tiger")

print(tiger)
// 輸出的結果為: Animal(catType: "Tiger")

10.static關鍵字

用static修飾的變數或者方法, 就會變成靜態變數和靜態方法, 並且保證在對應的作用域當中只有一份, 同時也不需要依賴例項化, 比如:

class Animals {
    static var catName: String!


    func catTypeName() {
        _ = "Tiger"
    }
}

Animals.catName = "Tiger"

print(Animals.catName)

// 輸出的結果為: Tiger

這裡的catType被宣告為static變數, 之後只要出現catType這個變數名, Xcode都會建議你用下標直接去宣告, 因為需要保證在Animals這個類的作用域裡, catType只保留一份.

11.lazy關鍵字

被lazy關鍵修飾的變數, 只有在第一次被呼叫的時候才會去計算它初始化值的屬性, 比如:

class SuvCar {
    var BydSuv = "S7"
}

class MpvCar  {
    lazy var suvCar = SuvCar()
    var mpvCars = [String]()
}

let mpvCar = MpvCar()

mpvCar.mpvCars.append("CarOne")
mpvCar.mpvCars.append("CarTwo")

print("I have \(mpvCar.mpvCars.count) MPV.")
// 輸出的結果為: I have 2 MPV.

print("I have a SUV Car, is \(mpvCar.suvCar.BydSuv)")
// 輸出的結果為: I have a SUV Car, is S7

在這裡需要注意兩點:

  • 1.用lazy修飾的變數必須是用var宣告的, 因為屬性的初始值可能在例項構造完成之後才會得到。而常量屬性在構造過程完成之前必須要有初始值,因此無法宣告成延遲屬性。

  • 2.如果被lazy修飾的變數沒有在初始化時就被多個執行緒呼叫, 那就沒有辦法保證它只被初始化一次了.

12.init關鍵字

在Swift 中也有對應的構造器, 來看看:

class Player {
    var coinsInPurse: Int

    init(coins: Int) {
        coinsInPurse = 1000
    }
}

這樣子coinsInPurse的值就為1000了.

還有一種用法, 就是在init後面加個”?”號, 表明該構造器可以允許失敗

struct Animal {
    let species: String
    init?(species: String) {
        if species.isEmpty { return nil }
        self.species = species
    }
}

let someCreature = Animal(species: "Giraffe")

if let giraffe = someCreature {
    print("An animal was initialized with a species of \(giraffe.species)")
}

let anonymousCreature = Animal(species: "")

if anonymousCreature == nil {
    print("The anonymous creature could not be initialized")
}

13.convenient關鍵字

該關鍵字是用來修飾init的, 經過convenient修飾的init方法, 表明該init方式是比較次要, 輔助型的, 比如:

class Food {
    var name: String
    init(name: String) {
        self.name = name
    }
    convenience init() {
        self.init(name: "[Unnamed]")
    }
}

14.required關鍵字

required也是用來修飾init方法的, 用required修飾說明該構造方法是必須實現的, 比如:

class SomeClass {
    required init() {
        // init body
    }
}

PS: 如果一個子類繼承了父類required修飾的init方法, 就必須得去實現該init方法, 但子類可以覺得它之後繼承於它的子類可以實現該方法.

15.deinit關鍵字

在Swift中, 有一個類似dealloc方法, 就是deinit, 但有一些區別, dealloc方法是在引用計數為0的時候, 也就是被釋放的時候才會呼叫, 而deinit是在例項不再引用的自動呼叫, 並且不用手動去管理引用計數, 比如:

class Bank {
    static var coinsInBank = 10_000

    static func vendCoins(var numberOfConisToVend: Int) -> Int {
        numberOfConisToVend = min(numberOfConisToVend, coinsInBank)

        coinsInBank -= numberOfConisToVend

        return numberOfConisToVend
    }

    static func receiveCoins(coins: Int) {
        //print("coinsInBank = \(coinsInBank)")

        coinsInBank += coins
    }
}

class Player {
    var coinsInPurse: Int

    init(coins: Int) {
        coinsInPurse = Bank.vendCoins(coins)
    }

    func winCoins(coins: Int) {
        coinsInPurse += Bank.vendCoins(coins)
    }

    deinit {
        Bank.receiveCoins(coinsInPurse)

        print("Player is nil.")
    }
}

var playerOne: Player? = Player(coins: 100)

print("A new player has joined the game with \(playerOne!.coinsInPurse) coins.")
// 輸出的結果為: A new player has joined the game with 100 coins

print("There are now \(Bank.coinsInBank) coins left in the bank.")
// 輸出的結果為: There are now 9900 coins left in the bank.

playerOne?.winCoins(2_000)

print("PlayerOne wn 2000 coins & now has \(playerOne!.coinsInPurse) coins.")
// 輸出的結果為: PlayerOne wn 2000 coins & now has 2100 coins.

print("The bank now only has \(Bank.coinsInBank) coins left.")
// 輸出的結果為: The bank now only has 7900 coins left.

playerOne = nil
// 這個時候就會去呼叫deinit方法, 輸出Player is nil.

16.is關鍵字

在Swift中, is關鍵字是用來判斷型別所使用的, 比如:

let number = ["xiaoming", 18]

for item in number {
    if item is Int {
        print("item is Int type.")

    } else if item is String {
        print("item is String type")

    }
}

// 輸出的結果為: 
// item is String type.
// item is Int type.

我們可以遍歷一個[NSObject]型別的陣列, 判斷裡面

17.throw, do-catch關鍵字

有關於throw, do-catch關鍵字的講解在前面幾章就有說明了1.Swift 錯誤資訊處理

18.extension關鍵字

extension的作用是在不改變原來的型別或者協議基礎下增加新的屬性或者方法, 比如:

class Person {
    var name = "xiaoming"
}

extension Person {
    var age: Int { return 20 }
}

let person = Person()

print("person name is \(person.name), age is \(person.age).")

// 輸出的結果為:
// person name is xiaoming, age is 20.

19.protocol關鍵字

protocol關鍵字在Swift中也是屬於協議的意思, 所謂的協議就是約束物件, 比如:

protocol Person {
    var name: String { get }
    var age: String { get }
}

class Xiaoming: Person {
    var name: String { return "xiaoming" }
    var age: String { return "20" }
}

class Laozhang: Person {
    var name: String
    var age: String

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

20.public關鍵字

public: 指的是可以訪問在一個模組內的任何實體, 也可以通過匯入該模組來訪問, 也就是我們經常在Objective-C中經常需要匯入的.h檔案中的方法, 該關鍵字可以用來修飾變數, 方法, 類, 列舉, 結構體等等之類, 比如:

public struct Person {
    // struct body
}

public enum CompassPoint {
    // enum body
}

public class SomePublecClass {}

public var somePublecVariable = 0

21.internal關鍵字

internal: 指的是可以訪問同一模組原始檔中得任何實體, 但不能從模組的外部去訪問該原始檔中得實體, 同樣, internal也可以修飾變數, 方法, 類, 列舉, 結構體等等之類等, 比如:

internal struct Person {
    // struct body
}

internal enum CompassPoint {
    // enum body
}

internal class SomePublecClass {}

internal var somePublecVariable = 0

22.private關鍵字

private: 指的是限制實體時能在原始檔內部使用, 外部不能訪問, private也同樣可以用來修飾變數, 方法, 類, 列舉, 結構體等等之類, 比如:

private struct Person {
    // struct body
}

private enum CompassPoint {
    // enum body
}

private class SomePublecClass {}

private var somePublecVariable = 0

好了, 這次就講到這裡, 如果還有其他關鍵, 我們陸續在該文章裡更新.