swift-06-關鍵字總結

附上資料地址:w3cschool-Swift 教程Swift中的關鍵字詳解html

1、與聲明有關的關鍵字

  • class:聲明一個類,或者類方法
class Person: NSObject {
        
    //聲明一個實例方法
    func run() {
        print("run")
    }
    //class修飾表示:聲明一個類方法
    class func work() {
        print("work")
    }

}
複製代碼
  • struct:聲明結構體,內部能夠聲明成員變量、成員方法。所以更接近於一個類,能夠說是類的一個輕量化實現
//聲明:
struct Person {
    var name:String
    var age:Int
    
    func introduce(){
        print("我叫:\(name),今年\(age)歲")
    }
}

//調用:
var person = Person(name: "xiaoMing",age: 20)

person.introduce()

//輸出:
我叫:xiaoMing,今年20歲
複製代碼
structclass比較
struct是結構體,class是類
一、struct是值類型,class是引用類型;意思是:聲明一個新的變量指向這個結構體,改變某個屬性,本來的結構體屬性不會發生變化;而類會隨着改變
`
代碼示例:

struct myStru {
    var width = 200
}

class myClass {
    var width = 200
}


//調用
var stu = myStru()
var stu2 = stu
stu2.width = 300
print(stu.width,stu2.width)
//200  300


var cls = myClass()
var cls2 = cls
cls2.width = 300
print(cls.width,cls2.width)
//300 300

`
二、struct不能被繼承,class能夠被繼承

三、用let修飾class對象,可以修改類的值;若要修改struct的值,要用var來修飾

四、struct是放在棧上,class是放在堆上,所以struct的訪問速度更快

五、struct裏面若是想聲明一個func來修改聲明的屬性,須要添加關鍵字mutating,才能編譯成功;而class不須要

六、全部的struct都有一個自動生成的成員構造器,而class須要本身生成

七、在struct中,成員變量能夠沒有初始值;但在class中,若是成員變量沒有初始值,就必須爲它寫一個構造函數
複製代碼
  • static:聲明靜態變量或者函數,它保證在對應的做用域當中只有一份, 同時也不須要依賴實例化。若是用於修飾函數,表示類方法,且不能被重寫
class Person: NSObject {

    var name: String
 
    //類方法,而且該方法不能被子類重寫
    static func run() {
        print(self.name + "running")
    }
}
複製代碼
staticclass比較
都是放在`func`前面用於指定類方法,只不過`static`修飾的類方法不能夠被重寫
複製代碼
  • typealias:各種起別名
//聲明
typealias abc = Int 
//調用
let a:abc = 100 
複製代碼
  • enum:枚舉,一種常見的數據類型。好處:使用枚舉能夠防止用戶使用無效值,同時該變量可使代碼更加清晰。
//寫法1,默認賦值0、一、二、3
enum Orientation1:Int{
        case East
        case South
        case West
        case North
    }

//寫法2
enum Orientation2:Int{
        case East,South,West,North
}

//調用 具體的值
       print(Orientation1.East.rawValue,Orientation1.South.rawValue,Orientation2.West.rawValue,Orientation2.North.rawValue)
        
//打印
0 1 2 3
        
複製代碼
  • extension:拓展,相似oc中的category分類,可是比分類更增強大。通常用於:
    1. 添加計算屬性
    2. 添加方法
    3. 添加初始化方法
    4. 添加附屬腳本,以下標腳本subscripts
    5. 添加並使用嵌套類型
    6. 遵循並實現某一協議
//給person類添加一個run方法
 class Person: NSObject {
    var name = "swift"
}


extension Person{
    
    func run() {
        print(self.name + "running")
    }
    
}

//調用
let per = Person()
per.run()
複製代碼
  • subscript:下標腳本,可讓 結構體枚舉使用下標功能。須要注意:subscript中能夠沒有set方法,可是要有get方法
struct Person {
    var age = 0
    var no  = 0
    subscript(index: Int) -> Int {
        set {
            if index == 0 {
                age = newValue
            } else {
                no = newValue
            }
        }
        get {
            if index == 0 {
                return age
            } else {
                return no
            }
        }
    }
}

var p = Person()
p[0] = 10
p[1] = 20

print(p.age)  // 10
print(p[0])   // 10

print(p.no)  // 20
print(p[1])  // 20
複製代碼

傳多個參數的例子:swift

class Matix {
    var data = [
       [0,0,0],
       [0,0,0],
       [0,0,0]
    ]
    subscript(row: Int , col: Int) -> Int {
        set {
            //守衛,不在這個範圍以內的就return
            guard row >= 0 && row < 3 && col >= 0 && col < 3 else {
                return
            }
            data[row][col] = newValue
        }
        get {
            guard row >= 0 && row < 3 && col >= 0 && col < 3 else {
                return 0
            }
            return data[row][col]
        }
    }
}


//調用
var m = Matix()
m[1, 1] = 3
m[0, 1] = 4
//這個超出範圍,直接return了
m[4, 4] = 9
print(m.data)

//打印
[[0, 4, 0], [0, 3, 0], [0, 0, 0]]

複製代碼
  • init:構造函數,初始化方法
class PerSon: NSObject {
    //若是不給屬性直接賦一個初始化值,就必須聲明構造函數
    var name:String
    
    init(name : String) {
        self.name = name
    }
    
}

//調用
let person = PerSon.init(name: "xiaoMing")
print(person.name)

//簡寫
let per = PerSon(name: "xiaoHong")
print(per.name)
複製代碼
  • deinit:析構函數,釋放方法。與oc中的dealloc同樣,用於:對象的銷燬、KVO移除、通知移除、NSTimer銷燬數組

  • protocol:協議markdown

2、與語句有關的關鍵字

  • fallthrough:穿透,在switch中,執行完當前case,繼續向下執行下一個case
//寫法1 = 寫法2

let num = 100

//寫法1
switch num {
case 100:
    fallthrough
case 200:
    print("100 + 200")
default:
    print("no")
}

//寫法2
switch num {
case 100,200:
    print("100 + 200")
default:
    print("no")
}
複製代碼
  • where:篩選條件用的,適用於do-catchswitchfor-in泛型協議
let array = [100,-50,36,-8,45]

//遍歷數組,只有值大於40的纔打印
for i in array where i > 40 {
    print(i)
}

//打印
100
45
複製代碼

3、與表達式和類型有關的關鍵字

  • is:類型檢查操做符,檢查一個實例是否屬於一個特定的子類,是返回true,不是返回false
// 1.定義數組
let array : [Any] = [12, "zhangsan"]

// 2.取出數組中的第一個
let objcFirst = array.first!

// 3.判斷第一個元素是不是一個Int類型
if objcFirst is Int {
    print("是Int類型")
} else {
    print("非Int類型")
}
複製代碼
  • as:類型轉換操做符,向上轉型,從派生類轉換成基類
//自己根據值定義的是int類型,經過as轉換成float類型
var number = 1 as Float
print(number) //1.0

var number = 1 as Float
至關於
var number = Float(1)
複製代碼
  • as!:向下轉型,轉成其子類類型,屬於強制轉型,若是轉換失敗會報錯閉包

  • as?:規則跟as!同樣,若是轉換失敗,會返回一個nil對象異步

// 1.定義數組
let array : [Any] = [12, "zhangsan"]

// 2.取出數組中最後一個元素
let objcLast = array.last!

// 3.轉成真正的類型來使用
// as? 將Any轉成可選類型,經過判斷可選類型是否有值,來決定是否轉化成功了
let name = objcLast as? String
print(name) // 結果:Optional("zhangsan")

// as! 將Any轉成具體的類型,若是不是該類型,那麼程序會崩潰
let name2 = objcLast as! String
print(name2) // 結果:zhangsan
複製代碼

4、特定上下文中的關鍵字

  • convenience:便利構造函數,用於修飾構造方法init,一般用於對系統類的init構造方法進行擴充,特色:async

    1. convenience一般寫在extension
    2. 須要在init以前添加convenience
    3. convenience中須要明確調用self.init()
/*
 對系統的init進行擴充,
 而且這個方法是公共的,
 若是子類要修改,就須要先實現父類方法,不能直接重寫
 */
 required convenience public init(...) {
    ...
    self.init()
    ...
 }
複製代碼
  • required:只用於修飾類的init初始化方法,表示該初始化方法是必須實現。要求子類必須實現父類的初始化方法

使用規則:ide

  1. 只能用於修飾類初始化方法
  2. 若是子類初始化方法的參數異於父類,要先實現父類的required init方法,這時不能用override,要一樣使用required修飾
  3. 若是子類沒有init方法,就不用實現父類的required init方法
//子類異於父類init方法狀況
class PerSon: NSObject {
    var name: String
    //若是子類要自定義init方法,要先實現父類的
    required init(name: String) {
        self.name = name
    }
}

class Student: PerSon {
    var age: Int = 0
    //先實現父類的
    required init(name:String) {
        super.init(name: name)
    }
    
    //再進行自定義init
    init(firstName: String, age:Int) {
        self.age = age
        super.init(name: firstName)
    }
     
}
複製代碼
  • mutating:在結構體或者枚舉中,放在func前,表示可修改它所屬的實例及實例屬性的值。用於在內部成員方法中修改爲員變量的值
//正常狀況
struct myStruct1 {
    var num1 = 100
    var num2 = 200
    var num3 = 300
 
}

var stu1 = myStruct1()
print(stu1.num1)//100
//直接修改爲員變量的值
stu1.num1 = 999
print(stu1.num1)//999


//經過內部方法改變值
struct myStruct2 {
    var num1 = 100
    var num2 = 200
    var num3 = 300
    
    
    mutating func changeNum(mark:Int) {
        self.num1 += mark
    }
}

//調用
var stu2 = myStruct2()
print(stu2.num1)//100
//經過調用結構體的成員方法來修改爲員變量的值
stu2.changeNum(mark: 99)
print(stu2.num1)//199
複製代碼
  • lazy:懶加載,修飾變量,只有在第一次調用的時候纔去初始化值
lazy var first = NSArray(objects: "1","2")
複製代碼
  • override:重寫父類的方法函數

  • final:能夠用來修飾classfuncvar,表示不可重寫。能夠將類或者類中的部分實現保護起來,從而避免子類破壞oop

  • inout:將值類型的對象 用 引用的方式傳遞,意思是能夠修改外部變量

func test(num: inout Int){
    //若是不加inout,改變外部變量會報錯
    num += 1
}

var a = 10
//調用的時候,是取地址操做
test(num: &a)

print(a)//11
複製代碼
  • defer:延遲執行,修飾一段函數內任一段代碼,使其必須在函數中其餘代碼執行完畢,函數即將結束前調用;若是有多個defer會自下而上的順序執行
func test(){
    print("函數開始")
    defer{
        print("執行defer1")
    }
    print("函數將結束")
    defer{
        
        print("執行defer2")
    }
    defer{
        print("執行defer3")
    }
}

//調用
test()

//打印   
函數開始
函數將結束
執行defer3
執行defer2
執行defer1
複製代碼

添加異步線程的狀況

func test(){
    print("函數開始")
    defer{
        print("執行defer1")
    }
    defer{
        print("執行defer2")
    }
                    DispatchQueue.main.asyncAfter(deadline: .now()+1) {
        print("異步執行完畢")
    }
    print("函數將結束")
    defer{
        print("執行defer3")
    }
}


test()

//打印:
函數開始
函數將結束
執行defer3
執行defer2
執行defer1
異步執行完畢

結論:
異步代碼的執行,不會影響defer的執行時間。事實上,defer的執行只和其所在的做用域有關,若是做用域即將被回收,那麼會在回收以前執行defer。
複製代碼
  • throws:放在可能會出現異常或者錯誤的函數後面,會把發生的錯誤帶出來,在調用的時候進行錯誤處理,節省了維護成本;通常調用的時候會配合trydo-catch一塊兒使用

代碼示例:

//錯誤類型枚舉
enum MyError : Error {
    case ErrorOne
    case ErrorTwo
    case ErrorOther
}


//使用:關鍵字所在的位置
func thisFuncCouldThrowError(_ type: Int) throws -> String{

    if type == 1 {
        return "成功"
    }else if type == 2{
        throw MyError.ErrorTwo
    }else{
        throw MyError.ErrorOther
    }

}

//調用,配合do-catch進行異常捕捉,拋出異常的方法在調用前要加 try 關鍵字

do {

    let stu = try thisFuncCouldThrowError(20)
    print("若是出現錯誤,這裏的代碼就不會執行了")
    print(stu)

} catch let err as MyError/* 這裏若是捕捉到的錯誤,屬於自定義枚舉的值,就進行相關處理*/{
    print("出現了錯誤")
    print(err)
} catch {
    //這裏必需要攜帶一個空的catch 否則會報錯。 緣由是可能遺漏
}


//打印
出現了錯誤
ErrorOther

複製代碼
  • rethrows:異常往上傳遞的關鍵字,針對的不是函數或者方法的自己,而是它攜帶的閉包類型的參數,當它的閉包類型的參數throws的時候,咱們要使用rethrows繼續將這個異常往上傳遞, 直到被調用者使用到。這相比throws多一個傳遞的環節
//throw函數做爲閉包參數傳入
//throws
func thisFuncCouldThrowError(_ type: Int) throws -> String{

    if type == 1 {
        return "成功"
    }else if type == 2{
        throw MyError.ErrorTwo
    }else{
        throw MyError.ErrorOther
    }

}

//rethrows
func thisFuncRethrows(_ throwsError:(Int) throws -> String) rethrows{

    do {

        let stu = try throwsError(20)
        print("若是出現錯誤,這裏的代碼就不會執行了")
        print(stu)

    } catch let err as MyError{
        throw err    //這裏進行了 再次throw
    } catch{

    }


}


//調用
let afunc = self.thisFuncCouldThrowError

do {
    try self.thisFuncRethrows(afunc)
    print("沒有錯誤,若是出現錯誤,這裏的代碼就不會執行了")
} catch let err as MyError {
    print("出現了錯誤")
    print(err)
}catch{
    //這裏必需要攜帶一個空的catch 否則會報錯。 緣由是可能遺漏
}
複製代碼

5、訪問權限關鍵字

swift中提供了5種訪問控制的權限: 由低到高:privatefileprivateinternalpublicopen

  • private:只能在當前類class中訪問、extension修飾的拓展類中能夠訪問,可是子類及其餘類不可訪問
  • fileprivate:只能在當前源文件中訪問。也就是說不一樣文件中的子類也沒法訪問
  • internal:默認的訪問級別。在源代碼所在的整個模塊均可以被訪問
  • public:能夠被任何人訪問,在本模塊中能夠被override(重寫)和繼承,但在其餘的模塊中不能夠被override和繼承
  • open:能夠被任何人使用,包含override和繼承
相關文章
相關標籤/搜索