更新: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. 類屬性的 set 和 get 方法
相信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的類,給它兩個屬性,hour和minute。
b -> 我們給hour了一個初始值 1 ,其中hour和minute是有換算關(guān)系的,所以我們?yōu)?code>minute添加set和get方法。
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
-
willSet和didSet屬于給類屬性添加觀察者。 -
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的類,給它兩個屬性,level和skill。
b -> 我們?yōu)?code>level添加了willSet和didSet方法。
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)方法sum和multiply。
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類,用于讀取和編輯文件,并定義了兩個方法openFile和writeFile。
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 -> 請注意在init 和 run前面都有關(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é)
好累呀,不想寫了。