Swift(七)類

更新:2018.05.24

整理了一下demo:SwiftDemo


Swift類是構(gòu)造代碼的一種通用而靈活的構(gòu)造體。
  • Swift中,用來描述對象,什么是?拿人類來舉例,整個人類就相當于一個,這些不同的人類各不相同,而又有一些共同點,比如如都是直立行走,都會吃飯睡覺等等等等。每一個人類就是一個對象,而每一個人類是屬于亞洲人種、歐洲人種、男人、女人、老人還是小孩,這就是一個人類的屬性。每個人類都會有一些自己的行為,比如上班、做飯、旅游,這就是這個人類具有的方法。
  • 通常來說,一個類的定義包含兩部分內(nèi)容,一部分是類的屬性,另一部分是它所擁有的方法。例如人類:每個人類都有自己的名字、性別等,這是人類的屬性,每個人類還擁有吃飯、睡覺、上班等行為。
  • 類與結(jié)構(gòu)體相似但不同,類和結(jié)構(gòu)體都有屬性,都可以定義方法,但類是引用類型,結(jié)構(gòu)體是值類型
  • 與OC不同,Swift不要求你為自定義的類去創(chuàng)建獨立的接口和實現(xiàn)文件,你所要做的就是在一個單一文件中定義一個類,系統(tǒng)會自動生成面向其他代碼的外部接口。

1. 定義

與結(jié)構(gòu)體的定義方法相同,類使用class關(guān)鍵字

class 類名 {
  屬性列表
方法列表
}

這里我們同樣以人類為例,創(chuàng)建一個類:

   class People {
       var age:Int
       var sex:String
       var name:String
       
       init() {
           self.age = 0
           self.sex = ""
           self.name = ""
       }
       
       func introduce() {
           print("My name is \(name), I`m a \(sex), \(age) years old.")
       }
   }

a -> 我們定義了一個類People,給People設(shè)置了三個屬性:name、sex、age
b -> Swift要求定義類時,類的屬性一定要初始化,這里我加了一個init()方法初始化屬性,當然也可以直接給屬性賦值。

       var age:Int = 0
       var sex:String = ""
       var name:String = ""

c -> 接著又給People添加了一個實例方法introduce,輸出屬性信息。

接下來讓我們使用一下這個類

        let people = People()
        people.name = "LiLei"
        people.sex = "boy"
        people.age = 15
        people.introduce()

#輸出結(jié)果:
        My name is LiLei, I`m a boy, 15 years old.

如果你覺得一個一個給屬性賦值比較麻煩的話,也可以這樣做:

    class People {
        var age:Int
        var sex:String
        var name:String
        
        init() {
            self.age = 0
            self.sex = ""
            self.name = ""
        }
        
        init(name:String, age:Int, sex:String) {
            self.name = name
            self.age = age
            self.sex = sex
        }
        
        func introduce() {
            print("My name is \(name), I`m a \(sex), \(age) years old.")
        }
    }
#調(diào)用
        let people2 = People.init(name: "LiLei", age: 15, sex: "boy")
        people2.introduce()

2. 類屬性的 setget 方法

相信OC中的set和get方法大家都很熟悉了,基本來說,set就是設(shè)置,get就是獲取。

    class Time {
        var hour:Int = 1
        var minute:Int {
            get {
                return self.hour * 60
            }
            set(newMinute) {
                self.hour = newMinute/60
            }
        }
    }

#調(diào)用
        let time = Time()
        print(time.hour)
        print(time.minute)

#輸出
1
60

a -> 在上面代碼中,我們創(chuàng)建了一個Time的類,給它兩個屬性,hourminute。
b -> 我們給hour了一個初始值 1 ,其中hourminute是有換算關(guān)系的,所以我們?yōu)?code>minute添加setget方法。
c ->minute屬性進行get操作時,返回hour乘以60之后的結(jié)果;當minute進行set操作時,同時設(shè)置hour的值為minute除以60后的結(jié)果。
d -> 輸出:我們可以看到,hour的值依然是1,mintue的值是60。

如果我們給mintue賦值了呢?

        time.minute = 360
        print(time.hour)
        print(time.minute)
#輸出
6
360

e -> 可以看到,hour的值變成了6。

3. willSet和didSet

  • willSetdidSet 屬于給類屬性添加觀察者。
  • willSet設(shè)置屬性值之前被調(diào)用。
  • didSet設(shè)置屬性值之后被調(diào)用。
  • 在實現(xiàn)willSet時,新的屬性值將被作為常量參數(shù)來傳遞,可以給這個參數(shù)一個名字,如果沒有,這個參數(shù)就迷人被命名為newValue。
    class Role {
        var skill : Int = 1
        var level : Int = 1 {
            
            willSet {
                print("角色即將升級,等級將要到達 \(newValue) ")
            }
            
            didSet {
                if oldValue >= level {
                    print("升級失敗!!!")
                } else {
                    print("角色已經(jīng)升級,等級到達 \(level)")
                }
            }
        }
    }

#調(diào)用
        let role = Role()
        role.level = 2
        role.level = 2

#輸出

角色即將升級,等級將要到達 2 
角色已經(jīng)升級,等級到達 2
角色即將升級,等級將要到達 2 
升級失敗!!!

a -> 在上面代碼中,我們創(chuàng)建了一個Role的類,給它兩個屬性,levelskill。
b -> 我們?yōu)?code>level添加了willSetdidSet方法。
c ->willSet方法中,調(diào)用此方法時,輸出提示語,其中newValue是默認參數(shù)名。
d ->didSet方法中,調(diào)用此方法,判斷level是否有增長,輸出條件語句。oldValue是舊值的默認參數(shù)名。

4. 靜態(tài)方法

  • 靜態(tài)方法,如果操作不需要具體實例,我們就可以定義近靜態(tài)方法,反之,如果某些操作是需要具體實例的,那就需要定義實例化方法。
  • 在OC中,我一般是叫類方法,比如封裝網(wǎng)絡(luò)請求時,一般是不需要實例的,就直接定義類方法。
  • Swift中,可以為類、結(jié)構(gòu)體和枚舉定義靜態(tài)方法,在為枚舉和結(jié)果體定義靜態(tài)方法時,使用關(guān)鍵字static。為類定義靜態(tài)方法時,使用class關(guān)鍵字。
    class MathTool {
        class func sum(number1:Int ,number2:Int) -> Int {
            return number1 + number2
        }
        class func multiply(num1:Int ,num2:Int) -> Int {
            return num1 * num2
        }
    }

#調(diào)用
        print(MathTool.sum(number1: 10, number2: 1))
        print(MathTool.multiply(num1: 2, num2: 4))

#輸出
11
8

a -> 在上面代碼中,創(chuàng)建了一個MathTool的類,并創(chuàng)建了兩個靜態(tài)方法summultiply
b -> 調(diào)用的時候可以直接用類名調(diào)用,不需要實例化。如果某些地方不需要實例化,建議使用靜態(tài)方法。

5. 類的析構(gòu)

Swift和Object-C都是通過ARC來管理內(nèi)存的,不需要我們對實例化的對象進行釋放操作,但有些環(huán)境中,可能需要我們自己去清理一些額外的資源,比如創(chuàng)建了一個自定義的類,這個類打開了一個文件,并寫入若干數(shù)據(jù),就需要我們再類實例被釋放之前關(guān)閉該文件。

    class FileManager {
        func openFile() {
            print("open file from the resorce")
        }
        func writeFile() {
            print("Write the data into the file")
        }
        deinit {
            print("delete the fileManager")
        }
    }

#調(diào)用
        var fileManager:FileManager? = FileManager()
        fileManager?.openFile()
        fileManager?.writeFile()
        fileManager = nil

#輸出
open file from the resorce
Write the data into the file
delete the fileManager

a -> 在上面例子中,我們定義了一個FileManager類,用于讀取和編輯文件,并定義了兩個方法openFilewriteFile。
b -> 在最后,添加了一個deinit,這個方法就是析構(gòu)函數(shù),當實例的引用計數(shù)為0時,系統(tǒng)自動調(diào)用這個方法,在輸出結(jié)果中可以看出。

6. 繼承

  • 繼承在OC中已經(jīng)很常用了。在Swift中,繼承是類所特有的,當一個類繼承其他類時,繼承類就稱為子類,被繼承的類稱為父類超類。
  • 通過繼承特性,子類可以使用父類的方法和屬性以及下標腳本,也可以重寫父類。

我們拿動物來舉例:

    class Animal {
        func run() {
            print("I can run")
        }
    }

a -> 我們創(chuàng)建了一個Animal的類,給它一個方法 run,然后我們?nèi)?chuàng)建一個大象的子類。

    class Elephant:Animal {
        var name:String
        override init() {
            self.name = "elephant"
        }
        
        override func run() {
            print("I'm a \(name), I can run.")
        }
        
    }

b -> 我們定義了一個子類 Elephant 請注意定義子類的寫法,Elephant:Animal和OC的很像。
c -> 在子類中可以添加父類沒有的方法或?qū)傩?,這里添加了一個name屬性并初始化。
d -> 請注意在initrun前面都有關(guān)鍵字 override。在重寫一個父類的方法時,你需要在重寫的方法前面加上override 關(guān)鍵字。如不使用的話,可能會出現(xiàn)各種錯誤,并且沒有使用override關(guān)鍵字的重寫,都被編譯器診斷為錯誤。

如果不希望父類的屬性、下標或方法被重寫,可以在父類中的屬性或方法前加final關(guān)鍵字,比如 final var、final func 等。
當子類中嘗試重寫 final方法或?qū)傩詴r,編譯器將會編譯錯誤。

7. 延時加載屬性lazy

延時加載屬性:當?shù)谝淮伪徽{(diào)用的時候,才對其進行初始化操作的屬性。當一個類擁有一個重度且不經(jīng)常使用的屬性時,比如這個屬性是一個復(fù)雜的類,初始化時會占用很多的資源,而這個屬性當前并不是必須使用的,此時就可以在聲明前加lazy關(guān)鍵字,添加一個延時加載,這樣就可以使用時再去進行初始化操作,提高程序運行效率。

    class Point {
        var pointValue:String = "1000"
    }
    
    class UserInfo {
        var username:String = "Coco"
        lazy var point:Point = Point()
    }
    
#調(diào)用
        let user = UserInfo()
        print(user.point.pointValue)

#輸出
1000

a -> 首先我們定義了一個積分類Point,Point中有一個屬性pointValue,然后定義了一個UserInfo類,有一個屬性是Point類型,但我們并不是馬上要使用這個屬性,假設(shè)這個屬性比較占用資源,所以在前面加了lazy關(guān)鍵字。


b -> 從圖中我們可以看出,我們此時已經(jīng)實例化了UserInfo類,username屬性有值,但point屬性還是nil,并沒有被實例化。

c -> 我們點擊step over按鈕往下走, point就不是nil了。

8. 類的引用特性

  • Swift中,元組、枚舉、結(jié)構(gòu)體屬于值類型,而類屬于引用類型。
  • 值類型的特征是在賦值、初始化和傳遞參數(shù)過程中的數(shù)據(jù)。并為這個數(shù)據(jù)創(chuàng)建一個嶄新獨立的實例。
  • 引用類型與值類型不用,引用類型的實例在被賦予到一個變量或常量或作為參數(shù)傳遞到另一個函數(shù)時,其操作的并不是類實例的拷貝,而是已存在的實例本身。就是說,假如值類型和引用類型都是一個常量的話,值類型傳遞的是對這個常量進行拷貝得到的另一個常量,而引用類型傳遞的就是這個常量本身。

舉例說明:

    class Car {
        var brand:String = "BMW"
    }

#調(diào)用
        let bmw = Car()
        print(bmw.brand)
        let toyota = bmw
        toyota.brand = "toyota"
        print(bmw.brand)
        print(toyota.brand)

#輸出
BMW
toyota
toyota

a -> 首先我們建立了一個Car類,里面有個屬性brand,然后我們在viewDidLoad中實例化一個類實例,輸出。
b -> 然后再創(chuàng)建一個常量 toyota等于bmw,并重新給brand賦值,然后輸出。
c -> 從結(jié)果我們可以看出,brand屬性的新值都是toyota。

9. 總結(jié)

好累呀,不想寫了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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