1. 程式人生 > >一覽Swift中的常用關鍵字 Swift - final關鍵字的介紹,以及使用場景

一覽Swift中的常用關鍵字 Swift - final關鍵字的介紹,以及使用場景

要學習Swift這門語言,就必須先了解Swift的關鍵字及對應的解釋。這裡就列一下在Swift中常用到的關鍵字。

關鍵字是類似於識別符號的保留字元序列,除非用重音符號(`)將其括起來,否則不能用作識別符號。關鍵字是對編譯器具有特殊意義的預定義保留識別符號。常見的關鍵字有以下4種。

 與宣告有關的關鍵字:class、deinit、enum、extension、func、import、init、let、protocol、static、struct、subscript、typealias和var。

與語句有關的關鍵字:break、case、continue、default、do、else、fallthrough、if、in、for、return、switch、where和while。

表示式和型別關鍵字:as、dynamicType、is、new、super、self、Self、Type、__COLUMN__、__FILE__、__FUNCTION__和__LINE__。

在特定上下文中使用的關鍵字:associativity、didSet、get、infix、inout、left、mutating、none、nonmutating、operator、override、postfix、precedence、prefix、rightset、unowned、unowned(safe)、unowned(unsafe)、weak和willSet。

 常見關鍵字的介紹:

1、class

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

class Person {
        
        // 給方法新增class關鍵字表示類方法
        class func work() {
            print("Type Method: Person: 學生.")
        }
  
    }

這樣我們就聲明瞭一個Student類。

 

2、let

Swift裡用let修飾的變數會是一個不可變的常量,即我們不可以對它進行修改。(注意:我們用let修飾的常量是一個類, 我們可以對其所在的屬性進行修改)比如:

class Student {
        let name = "xiaoMing"
        var age = 16
        var height = 160
    }

let studen = Student();
        studen.age +=  2
        print("student age is \(studen.age)")
        //輸出結果為student age is 18

在Student類裡name是不可變的,如果要對它進行修改就要將let改為var。注意:如果這個時候, 再宣告一個Student常量去引用student, 那麼studen1所指向的記憶體塊是和studen相同的.

 

3、var

Swift中用var修飾的變數是一個可變的變數,即可以對它進行修改。注意:我們不會用var去引用一個類, 也沒有必要。比如:

class Student {
        let name = "xiaoMing"
        var age = 16
        var height = 160
    }

 let studen = Student();
 studen.age +=  2
        
 var student2 = studen;
 student2.age -=  3
 print("student age is \(studen.age)")
 print("student2 age is \(student2.age)")
        
 /**
 輸出結果為
 student age is 15
 student2 age is 15
*/

由輸出結果可以看出他們所指向的記憶體塊都是同一個。

 

4、struct

在Swift中, 我們使用struct關鍵字去宣告結構體,Swift中的結構體並不複雜,與C語言的結構體相比,除了成員變數,還多了成員方法。使得它更加接近於一個類。個人認為可以理解為是類的一個輕量化實現。比如:

struct Person {
        var name:String
        var age:Int
        
        func introduce(){
            print("我叫:\(name),今年\(age)歲")
        }
    }

var person = Person(name: "xiaoMing",age: 20)
person.name = "xiaoMing"
print("person.name = \(person.name)")
person.introduce()
        
 /**
 輸出結果為:
 person.name = xiaoMing
 我叫:xiaoMing,今年20歲
 */

語法與C語言或者OC類似,Swift中的結構體,在定義成員變數時一定要註明型別。另外要注意一下的是,結構體屬於值型別,而Swift中的類屬於引用型別。他們在記憶體管理方面會有不同。

 

5.enum

在Swift中, 我們使用enum關鍵字去宣告列舉。列舉是一種常見的資料型別,他的主要功能就是將某一種有固定數量可能性的變數的值,以一組命名過的常數來指代。比如正常情況下方向有四種可能,東,南,西,北。我們就可以宣告一組常量來指代方向的四種可能。使用列舉可以防止使用者使用無效值,同時該變數可以使程式碼更加清晰。比如:

enum Orientation:Int{
        case East
        case South
        case West
        case North
    }
    /**
     或者
    enum Orientation:Int{
     case East,South,West,North
     }
     */

print(Orientation.East.rawValue)
        /**
         輸出結果 0
         
         */

注意:我們在定義列舉時,一定要指定型別,否則在使用時就會報錯。列舉型別的值如果沒有賦值,他就按照預設的走,可以賦予我們自己想要的值。

 

6、final

Swift中,final關鍵字可以在class、func和var前修飾。表示 不可重寫 可以將類或者類中的部分實現保護起來,從而避免子類破壞。詳細瞭解可以去看看(Swift - final關鍵字的介紹,以及使用場景

)。比如:

  class Fruit {
        //修飾詞 final 表示 不可重寫 可以將類或者類中的部分實現保護起來,從而避免子類破壞
        final  func price(){
            print("price")
        }
    }
    
    class Apple : Fruit {//類繼承
//        //重寫父類方法
//        override func price() {
//            print("重寫父類的price 方法")
//        }
}

這裡重寫 price()這個函式就會報錯。

 

7、override

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

class Fruit {
        var  sellPrice : Double = 0
        
        func info() -> () {
            print("fruit")
        }
        //修飾詞 final 表示 不可重寫 可以將類或者類中的部分實現保護起來,從而避免子類破壞
        final  func price(){
            print("price")
        }
    }
    
    class Apple : Fruit {//類繼承
        func eat () -> () {
            print("apple22222")
        }
        //重寫父類方法
        override func info() {
            print("重寫父類的info 方法00000")
        }
        //重寫父類的屬性  重寫父類的屬性或者方法要使用關鍵字 override 進行修飾
        override var sellPrice: Double {
            get {
                print("kkkkkkk\(super.sellPrice)")
                return super.sellPrice + 3
            }
            set {
                print("qqqqq")
                super.sellPrice = newValue * newValue
            }  
        }  
    }  


        let app = Apple()
        app.info()
        app.sellPrice = 20.0
        let  adb = app.sellPrice
        
        print("adb == \(adb)")
        
        /**
         輸出結果為:
         重寫父類的info 方法00000
         qqqqq
         kkkkkkk400.0
         adb == 403.0
         */

8、subscript

在Swft中,subscript關鍵字表示下標,可以讓class、struct、以及enum使用下標訪問內部的值。其實就可以快捷方式的設定或者獲取對應的屬性, 而不需要呼叫對應的方法去獲取或者儲存, 比如官網的一個例項:

struct Matrix {
        let rows: Int, columns: Int
        var grid: [Double]
        init(rows: Int, columns: Int) {
            self.rows = rows
            self.columns = columns
            grid = Array(repeating: 0.0, count: rows * columns)
        }
        
    
        func indexIsValid(row: Int, column: Int) -> Bool {
            return row >= 0 && row < rows && column >= 0 && column < columns
        }
        subscript(row: Int, column: Int) -> Double {
            get {
                assert(indexIsValid(row: row, column: column), "Index out of range")
                return grid[(row * columns) + column]
            }
            set {
                assert(indexIsValid(row: row, column: column), "Index out of range")
                grid[(row * columns) + column] = newValue
            }
        }
    }

var matrix = Matrix(rows: 2, columns: 2)
        matrix[0, 1] = 1.5
        matrix[1, 0] = 3.2
        print("matrix == \(matrix)")
        /**
         列印結果:
         matrix == Matrix(rows: 2, columns: 2, grid: [0.0, 1.5, 3.2000000000000002, 0.0])
         
         */

 

9、static

Swift中,用static關鍵字宣告靜態變數或者函式,它保證在對應的作用域當中只有一份, 同時也不需要依賴例項化。注意:(用static關鍵字指定的方法是類方法,他是不能被子類重寫的)比如:

class Person {
        
        // 給方法新增class關鍵字表示建立類方法
        class func work() {
            print("Type Method: Person: 學生.")
        }
        
        // 使用static關鍵字建立類方法
        static func ageOfPerson(name: String) {
            print("Type Method: Person name: \(name)")
        }
        
        // 可以和類方法重名, 以及一樣的引數.
        func nameOfPerson(name: String) {
            print("Instance Method: person name \(name)")
        }
        
    }
    
    class Student: Person {
        
        //注意 子類Student的例項方法work(), 和父類的類方法work()沒有關係, 二者不在同一個級別上, 不存在同名問題.
        func work() {
            print("Instance Method: Student: University Student")
        }
    }

 

 

10、mutating

Swift中,mutating關鍵字指的是可變即可修改。用在structure和enumeration中,雖然結構體和列舉可以定義自己的方法,但是預設情況下,例項方法中是不可以修改值型別的屬性。為了能夠在例項方法中修改屬性值,可以在方法定義前新增關鍵字mutating。比如:

struct rect {
        var width = 0,height = 0
        mutating func changeRect(x:Int, y:Int) {
            self.width += x
            self.height += y
        }
        
    }
    
   
    enum Direction {
        case Top, Left, Right, Bottom
        mutating func lookDirection() {
            switch self {
            case .Top:
                self = .Top
            case .Left:
                self = .Left
            case .Right:
                self = .Right
            case .Bottom:
                self = .Bottom
            }
            print("self === \(self)")
        }
    }


    var re = rect(width: 5, height: 5)
        re.changeRect(x: 32, y: 15)
        print("re = \(re)")
        
        /**
         列印結果為:re = rect(width: 37, height: 20)
         */
        
        var dir = Direction.Left
        dir.lookDirection()
        /**
         列印結果為:self === Left
         */

 

 

11、typealias

在Swift中,使用關鍵字typealias定義類型別名(typealias就相當於objective-c中的typedef),就是將型別重新命名,看起來更加語義化。比如:

typealias Width = CGFloat
        typealias Height = CGFloat
        func rectangularArea(width:Width, height:Height) -> Double {
            return Double(width*height)
        }
        let area: Double = rectangularArea(width: 10, height: 20)
        print(area)
        
        /**
         結果為:200.0
         */

 

 

12、lazy

在Swift中,lazy關鍵修飾的變數, 只有在第一次被呼叫的時候才會去初始化值(即懶載入)。比如:

lazy var first = NSArray(objects: "1","2")

 

注意:用lazy修飾的變數必須是用var宣告的, 因為屬性的初始值可能在例項構造完成之後才會得到。而常量屬性在構造過程完成之前必須要有初始值,因此無法宣告成延遲屬性。如果被lazy修飾的變數沒有在初始化時就被多個執行緒呼叫, 那就沒有辦法保證它只被初始化一次了。

 

13、init

在Swift 中,init關鍵字也表示構造器。比如:

class PerSon {
        var name:String
        init?(name : String) {
            if name.isEmpty { return nil }
            self.name = name
        }
        
    }

let person = PerSon.init(name: "xiaoQiang")
        print("person is name \(String(describing: person?.name))")

/**
列印結果為:person is name Optional("xiaoQiang")
*/

 

在例子裡在init後面加個”?”號, 表明該構造器可以允許失敗。

 

14、required

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

 class PerSon {
        var name:String
        required init(name : String) {
            self.name = name
        }
    }
    
    class Student: PerSon {
        required init(name:String) {
            super.init(name: name)
        }
    }

 

從上面的程式碼示例中不難看出,如果子類需要新增異於父類的初始化方法時,必須先要實現父類中使用required修飾符修飾過的初始化方法,並且也要使用required修飾符而不是override

注意: (1)required修飾符只能用於修飾類初始化方法。

    (2)當子類含有異於父類的初始化方法時(初始化方法引數型別和數量異於父類),子類必須要實現父類的required初始化方法,並且也要使用required修飾符而不是override

    (3)當子類沒有初始化方法時,可以不用實現父類的required初始化方法。

 

15、extension

在swift中,extension與Objective-C的category有點類似,但是extension比起category來說更加強大和靈活,它不僅可以擴充套件某種型別或結構體的方法,同時它還可以與protocol等結合使用,編寫出更加靈活和強大的程式碼。它可以為特定的class, strut, enum或者protocol新增新的特性。當你沒有許可權對原始碼進行改造的時候,此時可以通過extension來對型別進行擴充套件。extension有點類似於OC的類別 -- category,但稍微不同的是category有名字,而extension沒有名字。在Swift 中的可以擴充套件以下幾個:

  (1)定義例項方法和型別方法

  (2)新增計算型屬性和計算靜態屬性

  (3)定義下標

  (4)提供新的構造器

  (5)定義和使用新的巢狀型別

  (6)使一個已有型別符合某個介面

比如:

//    新增計算屬性
extension Double {
    var km: Double { return self * 1_000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
}
class Person {
    var name:String
    var age:Int = 0
    init?(name:String) {
        if name.isEmpty {
            return nil
        }
        self.name = name
    }
    
}

extension Person {
    //新增方法
    func run() {
        print("走了50公里")
    }
}


 let oneInch = 25.4.km
        print("One inch is \(oneInch) meters")
        /**
         
         輸出結果:One inch is 25400.0 meters
         */
        
        let person = Person.init(name: "xiaom")
        person?.run()
        /**
         
         輸出結果:走了50公里
         */

 

想要了解詳情可以去看看這篇文漲(apple documents - extensions

 

16、convenient

swift中,使用convenience修飾的建構函式叫做便利建構函式 。便利建構函式通常用在對系統的類進行建構函式的擴充時使用。便利建構函式有如下幾個特點:  

  (1)便利建構函式通常都是寫在extension裡面  

  (2)便利函式init前面需要載入convenience   

  (3)在便利建構函式中需要明確的呼叫self.init()  

比如:

extension UIButton{
    //swit中類方法是以class開頭的方法,類似於oc中+開頭的方法
    class func createButton(imageName:String)->UIButton{
        
        let btn=UIButton()
        btn.setImage(UIImage(named:imageName), for: .normal)
        btn.sizeToFit()
        
        return btn
    }
    /*
     convenience:便利,使用convenience修飾的建構函式叫做便利建構函式
     便利建構函式通常用在對系統的類進行建構函式的擴充時使用。
     
     */
    
    convenience init(imageName:String,bgImageName:String){
        self.init()
        if !imageName.isEmpty {
            setImage(UIImage(named:imageName), for: .normal)
        }
        if !imageName.isEmpty {
            setBackgroundImage(UIImage(named:bgImageName), for: .normal)
        }
        sizeToFit()
    }
}


let btn = UIButton.init(imageName: "huanying", bgImageName: "")
        btn.frame = CGRect.init(x: 10, y: 120, width: 100, height: 30)
        btn.backgroundColor = UIColor.red
        self.view.addSubview(btn)

 

 

17、deinit

在Swift中,deinit屬於解構函式,當物件結束其生命週期時(例如物件所在的函式已呼叫完畢),系統自動執行解構函式。和OC中的dealloc 一樣的,通常在deinit和dealloc中需要執行的操作有:  

  (1)物件銷燬

  (2)KVO移除

  (3)移除通知

  (4)NSTimer銷燬

 

18、fallthrough

 swift語言特性switch語句的break可以忽略不寫,滿足條件時直接跳出迴圈.fallthrough的作用就是執行完當前case,繼續執行下面的case.類似於其它語言中省去break裡,會繼續往後一個case跑,直到碰到break或default才完成的效果。比如:

 var myClass = MyClass(parm: 9)
        let index = 15
        switch index {
            case 1  :
                print( "index is 100")
            case 10,15  :
                print( "index is either 10 or 15")
            case 5  :
                print( "index is 5")
            default :
                print( "default case")
        }
        
        /**
         輸出結果:index is either 10 or 15
         */

  let index = 15
        switch index {
        case 100  :
            print( "index is 100")
            fallthrough
        case 10,15  :
            print( "index is either 10 or 15")
            fallthrough
        case 5  :
            print( "index is 5")
        default :
            print( "default case")
        }

/**

列印結果:
    index is either 10 or 15
    index is 5
    
*/

 

 

19、protocol

在Swift中,protocol關鍵字也是屬於協議。比如:

protocol PersonProtocol {
    var height: Int { get set }
    var weight: Int { get }
    func getName()
    func getSex()
    func getAge(age: Int)
}

struct Student: PersonProtocol {
    var height = 178
    var weight = 120
    func getName() {
        print("MelodyZhy")
    }
    func getSex() {
        print("boy")
    }
    func getAge(age: Int) {
        print("age = \(age)")
    }
}

 var stu = Student()
        let height1 = stu.height
        stu.height = 180
        print("height1 = \(height1) height2 = \(stu.height)")
        
        /**
         輸出結果:
         height1 = 178 height2 = 180
         */

 

 

20、open

在Swift中,open修飾的物件表示可以被任何人使用,包括override和繼承。例如:

import UIKit
// 在本類外的範圍外可以被繼承
open class ParentClass1: NSObject {
    // 這個方法在任何地方都可以被override
    open func abc() {
        print("abc")
    }
}class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //這裡可以呼叫module1的方法
        let child = ChildrenClass1.init()
        child.abc()
        /**
         列印結果:abc
         */
    }

    class ChildrenClass1: ParentClass1 {
        
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

 

 

21、public

在Swift中,public表示公有訪問許可權,類或者類的公有屬性或者公有方法可以從檔案或者模組的任何地方進行訪問。但在其他模組(一個App就是一個模組,一個第三方API, 第三等方框架等都是一個完整的模組)不可以被override和繼承,而在本模組內可以被override和繼承。

import UIKit
// 在module1外的範圍外可以被繼承
public class ParentClass1: NSObject {
    // 這個方法在任何地方都可以被override
   public func abc() {
        print("abc")
    }
}class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //這裡可以呼叫module1的方法
        let child = ChildrenClass1.init()
        child.abc()
        
        /**
         列印結果:abc11
         */
    }

class ChildrenClass1: ParentClass1 {
        override func abc() {
            print("abc11")
        }
    
        func run() -> Void {
            print("run")
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

 

 

22、internal

在Swift中,public表示內部的訪問許可權。即有著internal訪問許可權的屬性和方法說明在模組內部可以訪問,超出模組內部就不可被訪問了。在Swift中預設就是internal的訪問許可權。

import UIKit

// 在module1外的範圍外可以被繼承
internal class ParentClass1: NSObject {
    // 這個方法在任何地方都可以被override
    func abc() {
        print("abc")
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //這裡可以呼叫module1的方法
        let child = ChildrenClass1.init()
        child.abc()
        
        /**
         列印結果:abc11
         */
    }

class ChildrenClass1: ParentClass1 {
        override func abc() {
            print("abc11")
        }
    
        func run() -> Void {
            print("run")
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

 

 

23、private

在Swift中,private私有訪問許可權。被private修飾的類或者類的屬性或方法可以在同一個物理檔案中訪問。如果超出該物理檔案,那麼有著private訪問許可權的屬性和方法就不能被訪問。比如:

import UIKit

// 在module1外的範圍外可以被繼承
internal class ParentClass1: NSObject {
    // 這個方法在任何地方都可以被override
 private func abc() {
        print("abc")
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //這裡可以呼叫module1的方法
        let child = ChildrenClass1.init()
        child.abc()
        
        /**
         列印結果:abc11
         */
    }

class ChildrenClass1: ParentClass1 {
    
    /**
     這裡就會報錯
     */
    
    override func abc() {
        print("abc11")
    }
}
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

 

 

24、fileprivate

在Swift中,fileprivate訪問級別所修飾的屬性或者方法在當前的Swift原始檔裡可以訪問。比如:

import UIKit

// 在module1外的範圍外可以被繼承
internal class ParentClass1: NSObject {
    // 這個方法在任何地方都可以被override
 fileprivate func abc() {
        print("abc")
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //這裡可以呼叫module1的方法
        let child = ChildrenClass1.init()
        child.abc()
        
        /**
         列印結果:abc11
         */
    }

class ChildrenClass1: ParentClass1 {
    
    override func abc() {
        print("abc11")
    }
}
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

 

說明:5種修飾符訪問許可權排序open> public > interal > fileprivate > private。

 

 

參考文獻:

  http://www.jianshu.com/p/6daa3e309235

  http://blog.csdn.net/qq350116542/article/details/50629260

  http://www.jianshu.com/p/1ae8c364954a 

   

要學習Swift這門語言,就必須先了解Swift的關鍵字及對應的解釋。這裡就列一下在Swift中常用到的關鍵字。

關鍵字是類似於識別符號的保留字元序列,除非用重音符號(`)將其括起來,否則不能用作識別符號。關鍵字是對編譯器具有特殊意義的預定義保留識別符號。常見的關鍵字有以下4種。

 與宣告有關的關鍵字:class、deinit、enum、extension、func、import、init、let、protocol、static、struct、subscript、typealias和var。

與語句有關的關鍵字:break、case、continue、default、do、else、fallthrough、if、in、for、return、switch、where和while。

表示式和型別關鍵字:as、dynamicType、is、new、super、self、Self、Type、__COLUMN__、__FILE__、__FUNCTION__和__LINE__。

在特定上下文中使用的關鍵字:associativity、didSet、get、infix、inout、left、mutating、none、nonmutating、operator、override、postfix、precedence、prefix、rightset、unowned、unowned(safe)、unowned(unsafe)、weak和willSet。

 常見關鍵字的介紹:

1、class

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

class Person {
        
        // 給方法新增class關鍵字表示類方法
        class func work() {
            print("Type Method: Person: 學生.")
        }
  
    }

這樣我們就聲明瞭一個Student類。

 

2、let

Swift裡用let修飾的變數會是一個不可變的常量,即我們不可以對它進行修改。(注意:我們用let修飾的常量是一個類, 我們可以對其所在的屬性進行修改)比如:

class Student {
        let name = "xiaoMing"
        var age = 16
        var height = 160
    }

let studen = Student();
        studen.age +=  2
        print("student age is \(studen.age)")
        //輸出結果為student age is 18

在Student類裡name是不可變的,如果要對它進行修改就要將let改為var。注意:如果這個時候, 再宣告一個Student常量去引用student, 那麼studen1所指向的記憶體塊是和studen相同的.

 

3、var

Swift中用var修飾的變數是一個可變的變數,即可以對它進行修改。注意:我們不會用var去引用一個類, 也沒有必要。比如:

class Student {
        let name = "xiaoMing"
        var age = 16
        var height = 160
    }

 let studen = Student();
 studen.age +=  2
        
 var student2 = studen;
 student2.age -=  3
 print("student age is \(studen.age)")
 print("student2 age is \(student2.age)")
        
 /**
 輸出結果為
 student age is 15
 student2 age is 15
*/

由輸出結果可以看出他們所指向的記憶體塊都是同一個。

 

4、struct

在Swift中, 我們使用struct關鍵字去宣告結構體,Swift中的結構體並不複雜,與C語言的結構體相比,除了成員變數,還多了成員方法。使得它更加接近於一個類。個人認為可以理解為是類的一個輕量化實現。比如:

struct Person {
        var name:String
        var age:Int
        
        func introduce(){
            print("我叫:\(name),今年\(age)歲")
        }
    }

var person = Person(name: "xiaoMing",age: 20)
person.name = "xiaoMing"
print("person.name = \(person.name)")
person.introduce()
        
 /**
 輸出結果為:
 person.name = xiaoMing
 我叫:xiaoMing,今年20歲
 */

語法與C語言或者OC類似,Swift中的結構體,在定義成員變數時一定要註明型別。另外要注意一下的是,結構體屬於值型別,而Swift中的類屬於引用型別。他們在記憶體管理方面會有不同。

 

5.enum

在Swift中, 我們使用enum關鍵字去宣告列舉。列舉是一種常見的資料型別,他的主要功能就是將某一種有固定數量可能性的變數的值,以一組命名過的常數來指代。比如正常情況下方向有四種可能,東,南,西,北。我們就可以宣告一組常量來指代方向的四種可能。使用列舉可以防止使用者使用無效值,同時該變數可以使程式碼更加清晰。比如:

enum Orientation:Int{
        case East
        case South
        case West
        case North
    }
    /**
     或者
    enum Orientation:Int{
     case East,South,West,North
     }
     */

print(Orientation.East.rawValue)
        /**
         輸出結果 0
         
         */

注意:我們在定義列舉時,一定要指定型別,否則在使用時就會報錯。列舉型別的值如果沒有賦值,他就按照預設的走,可以賦予我們自己想要的值。

 

6、final

Swift中,final關鍵字可以在class、func和var前修飾。表示 不可重寫 可以將類或者類中的部分實現保護起來,從而避免子類破壞。詳細瞭解可以去看看(Swift - final關鍵字的介紹,以及使用場景

)。比如:

  class Fruit {
        //修飾詞 final 表示 不可重寫 可以將類或者類中的部分實現保護起來,從而避免子類破壞
        final  func price(){
            print("price")
        }
    }
    
    class Apple : Fruit {//類繼承
//        //重寫父類方法
//        override func price() {
//            print("重寫父類的price 方法")
//        }
}

這裡重寫 price()這個函式就會報錯。

 

7、override

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

class Fruit {
        var  sellPrice : Double = 0
        
        func info() -> () {
            print("fruit")
        }
        //修飾詞 final 表示 不可重寫 可以將類或者類中的部分實現保護起來,從而避免子類破壞
        final  func price(){
            print("price")
        }
    }
    
    class Apple : Fruit {//類繼承
        func eat () -> () {
            print("apple22222")
        }
        //重寫父類方法
        override func info() {
            print("重寫父類的info 方法00000")
        }
        //重寫父類的屬性  重寫父類的屬性或者方法要使用關鍵字 override 進行修飾
        override var sellPrice: Double {
            get {
                print("kkkkkkk\(super.sellPrice)")
                return super.sellPrice + 3
            }
            set {
                print("qqqqq")
                super.sellPrice = newValue * newValue
            }  
        }  
    }  


        let app = Apple()
        app.info()
        app.sellPrice = 20.0
        let  adb = app.sellPrice
        
        print("adb == \(adb)")
        
        /**
         輸出結果為:
         重寫父類的info 方法00000
         qqqqq
         kkkkkkk400.0
         adb == 403.0
         */

8、subscript

在Swft中,subscript關鍵字表示下標,可以讓class、struct、以及enum使用下標訪問內部的值。其實就可以快捷方式的設定或者獲取對應的屬性, 而不需要呼叫對應的方法去獲取或者儲存, 比如官網的一個例項:

struct Matrix {
        let rows: Int, columns: Int
        var grid: [Double]
        init(rows: Int, columns: Int) {
            self.rows = rows
            self.columns = columns
            grid = Array(repeating: 0.0, count: rows * columns)
        }
        
    
        func indexIsValid(row: Int, column: Int) -> Bool {
            return row >= 0 && row < rows && column >= 0 && column < columns
        }
        subscript(row: Int, column: Int) -> Double {
            get {
                assert(indexIsValid(row: row, column: column), "Index out of range")
                return grid[(row * columns) + column]
            }
            set {
                assert(indexIsValid(row: row, column: column), "Index out of range")
                grid[(row * columns) + column] = newValue
            }
        }
    }

var matrix = Matrix(rows: 2, columns: 2)
        matrix[0, 1] = 1.5
        matrix[1, 0] = 3.2
        print("matrix == \(matrix)")
        /**
         列印結果:
         matrix == Matrix(rows: 2, columns: 2, grid: [0.0, 1.5, 3.2000000000000002, 0.0])
         
         */

 

9、static

Swift中,用static關鍵字宣告靜態變數或者函式,它保證在對應的作用域當中只有一份, 同時也不需要依賴例項化。注意:(用static關鍵字指定的方法是類方法,他是不能被子類重寫的)比如:

class Person {
        
        // 給方法新增class關鍵字表示建立類方法
        class func work() {
            print("Type Method: Person: 學生.")
        }
        
        // 使用static關鍵字建立類方法
        static func ageOfPerson(name: String) {
            print("Type Method: Person name: \(name)")
        }
        
        // 可以和類方法重名, 以及一樣的引數.
        func nameOfPerson(name: String) {
            print("Instance Method: person name \(name)")
        }
        
    }
    
    class Student: Person {
        
        //注意 子類Student的例項方法work(), 和父類的類方法work()沒有關係, 二者不在同一個級別上, 不存在同名問題.
        func work() {
            print("Instance Method: Student: University Student")
        }
    }

 

 

10、mutating

Swift中,mutating關鍵字指的是可變即可修改。用在structure和enumeration中,雖然結構體和列舉可以定義自己的方法,但是預設情況下,例項方法中是不可以修改值型別的屬性。為了能夠在例項方法中修改屬性值,可以在方法定義前新增關鍵字mutating。比如:

struct rect {
        var width = 0,height = 0
        mutating func changeRect(x:Int, y:Int) {
            self.width += x
            self.height += y
        }
        
    }
    
   
    enum Direction {
        case Top, Left, Right, Bottom
        mutating func lookDirection() {
            switch self {
            case .Top:
                self = .Top
            case .Left:
                self = .Left
            case .Right:
                self = .Right
            case .Bottom:
                self = .Bottom
            }
            print("self === \(self)")
        }
    }


    var re = rect(width: 5, height: 5)
        re.changeRect(x: 32, y: 15)
        print("re = \(re)")
        
        /**
         列印結果為:re = rect(width: 37, height: 20)
         */
        
        var dir = Direction.Left
        dir.lookDirection()
        /**
         列印結果為:self === Left
         */

 

 

11、typealias

在Swift中,使用關鍵字typealias定義類型別名(typealias就相當於objective-c中的typedef),就是將型別重新命名,看起來更加語義化。比如:

typealias Width = CGFloat
        typealias Height = CGFloat
        func rectangularArea(width:Width, height:Height) -> Double {
            return Double(width*height)
        }
        let area: Double = rectangularArea(width: 10, height: 20)
        print(area)
        
        /**
         結果為:200.0
         */

 

 

12、lazy

在Swift中,lazy關鍵修飾的變數, 只有在第一次被呼叫的時候才會去初始化值(即懶載入)。比如:

lazy var first = NSArray(objects: "1","2")

 

注意:用lazy修飾的變數必須是用var宣告的, 因為屬性的初始值可能在例項構造完成之後才會得到。而常量屬性在構造過程完成之前必須要有初始值,因此無法宣告成延遲屬性。如果被lazy修飾的變數沒有在初始化時就被多個執行緒呼叫, 那就沒有辦法保證它只被初始化一次了。

 

13、init

在Swift 中,init關鍵字也表示構造器。比如:

class PerSon {
        var name:String
        init?(name : String) {
            if name.isEmpty { return nil }
            self.name = name
        }
        
    }

let person = PerSon.init(name: "xiaoQiang")
        print("person is name \(String(describing: person?.name))")

/**
列印結果為:person is name Optional("xiaoQiang")
*/

 

在例子裡在init後面加個”?”號, 表明該構造器可以允許失敗。

 

14、required

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

 class PerSon {
        var name:String
        required init(name : String) {
            self.name = name
        }
    }
    
    class Student: PerSon {
        required init(name:String) {
            super.init(name: name)
        }
    }

 

從上面的程式碼示例中不難看出,如果子類需要新增異於父類的初始化方法時,必須先要實現父類中使用required修飾符修飾過的初始化方法,並且也要使用required修飾符而不是override

注意: (1)required修飾符只能用於修飾類初始化方法。

    (2)當子類含有異於父類的初始化方法時(初始化方法引數型別和數量異於父類),子類必須要實現父類的required初始化方法,並且也要使用required修飾符而不是override

    (3)當子類沒有初始化方法時,可以不用實現父類的required初始化方法。

 

15、extension

在swift中,extension與Objective-C的category有點類似,但是extension比起category來說更加強大和靈活,它不僅可以擴充套件某種型別或結構體的方法,同時它還可以與protocol等結合使用,編寫出更加靈活和強大的程式碼。它可以為特定的class, strut, enum或者protocol新增新的特性。當你沒有許可權對原始碼進行改造的時候,此時可以通過extension來對型別進行擴充套件。extension有點類似於OC的類別 -- category,但稍微不同的是category有名字,而extension沒有名字。在Swift 中的可以擴充套件以下幾個:

  (1)定義例項方法和型別方法

  (2)新增計算型屬性和計算靜態屬性

  (3)定義下標

  (4)提供新的構造器

  (5)定義和使用新的巢狀型別

  (6)使一個已有型別符合某個介面

比如:

//    新增計算屬性
extension Double {
    var km: Double { return self * 1_000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
}
class Person {
    var name:String
    var age:Int = 0
    init?(name:String) {
        if name.isEmpty {
            return nil
        }
        self.name = name
    }
    
}

extension Person {
    //新增方法
    func run() {
        print("走了50公里")
    }
}


 let oneInch = 25.4.km
        print("One inch is \(oneInch) meters")
        /**
         
         輸出結果:One inch is 25400.0 meters
         */
        
        let person = Person.init(name: "xiaom")
        person?.run()
        /**
         
         輸出結果:走了50公里
         */

 

想要了解詳情可以去看看這篇文漲(apple documents - extensions

 

16、convenient

swift中,使用convenience修飾的建構函式叫做便利建構函式 。便利建構函式通常用在對系統的類進行建構函式的擴充時使用。便利建構函式有如下幾個特點:  

  (1)便利建構函式通常都是寫在extension裡面  

  (2)便利函式init前面需要載入convenience   

  (3)在便利建構函式中需要明確的呼叫self.init()  

比如:

extension UIButton{
    //swit中類方法是以class開頭的方法,類似於oc中+開頭的方法
    class func createButton(imageName:String)->UIButton{
        
        let btn=UIButton()
        btn.setImage(UIImage(named:imageName), for: .normal)
        btn.sizeToFit()
        
        return btn
    }
    /*
     convenience:便利,使用convenience修飾的建構函式叫做便利建構函式
     便利建構函式通常用在對系統的類進行建構函式的擴充時使用。
     
     */
    
    convenience init(imageName:String,bgImageName:String){
        self.init()
        if !imageName.isEmpty {
            setImage(UIImage(named:imageName), for: .normal)
        }
        if !imageName.isEmpty {
            setBackgroundImage(UIImage(named:bgImageName), for: .normal)
        }
        sizeToFit()
    }
}


let btn = UIButton.init(imageName: "huanying", bgImageName: "")
        btn.frame = CGRect.init(x: 10, y: 120, width: 100, height: 30)
        btn.backgroundColor = UIColor.red
        self.view.addSubview(btn)

 

 

17、deinit

在Swift中,deinit屬於解構函式,當物件結束其生命週期時(例如物件所在的函式已呼叫完畢),系統自動執行解構函式。和OC中的dealloc 一樣的,通常在deinit和dealloc中需要執行的操作有:  

  (1)物件銷燬

  (2)KVO移除

  (3)移除通知

  (4)NSTimer銷燬

 

18、fallthrough

 swift語言特性switch語句的break可以忽略不寫,滿足條件時直接跳出迴圈.fallthrough的作用就是執行完當前case,繼續執行下面的case.類似於其它語言中省去break裡,會繼續往後一個case跑,直到碰到break或default才完成的效果。比如:

 var myClass = MyClass(parm: 9)
        let index = 15
        switch index {
            case 1  :
                print( "index is 100")
            case 10,15  :
                print( "index is either 10 or 15")
            case 5  :
                print( "index is 5")
            default :
                print( "default case")
        }
        
        /**
         輸出結果:index is either 10 or 15
         */

  let index = 15
        switch index {
        case 100  :
            print( "index is 100")
            fallthrough
        case 10,15  :
            print( "index is either 10 or 15")
            fallthrough
        case 5  :
            print( "index is 5")
        default :
            print( "default case")
        }

/**

列印結果:
    index is either 10 or 15
    index is 5
    
*/

 

 

19、protocol

在Swift中,protocol關鍵字也是屬於協議。比如:

protocol PersonProtocol {
    var height: Int { get set }
    var weight: Int { get }
    func getName()
    func getSex()
    func getAge(age: Int)
}

struct Student: PersonProtocol {
    var height = 178
    var weight = 120
    func getName() {
        print("MelodyZhy")
    }
    func getSex() {
        print("boy")
    }
    func getAge(age: Int) {
        print("age = \(age)")
    }
}

 var stu = Student()
        let height1 = stu.height
        stu.height = 180
        print("height1 = \(height1) height2 = \(stu.height)")
        
        /**
         輸出結果:
         height1 = 178 height2 = 180
         */

 

 

20、open

在Swift中,open修飾的物件表示可以被任何人使用,包括override和繼承。例如:

import UIKit
// 在本類外的範圍外可以被繼承
open class ParentClass1: NSObject {
    // 這個方法在任何地方都可以被override
    open fu