類的屬性介紹
- Swift中屬性有多種
- 存儲屬性:存儲執行個體的常量和變量
- 計算屬性:通過某種方式計算出來的屬性
- 類屬性:與整個類自身相關的屬性
存儲屬性
- 存儲屬性是最簡單的屬性,它作為類執行個體的一部分,用于存儲常量和變量
- 可以給存儲屬性提供一個預設值,也可以在初始化方法中對其進行初始化
- 下面是存儲屬性的寫法
- age和name都是存儲屬性,用來記錄該學生的年齡和姓名
- chineseScore和mathScore也是存儲屬性,用來記錄該學生的國文分數和數學分數
class Student {
// 存儲屬性
var age : Int = 0
var name : String?
var chineseScore : Double = 0.0
var mathScore : Double = 0.0
}
// 建立學生對象
let stu = Student()
// 給存儲屬性指派
stu.age = 10
stu.name = "why"
stu.chineseScore = 89.0
stu.mathScore = 98.0
計算屬性
- 計算屬性并不存儲實際的值,而是提供一個
和一個可選的getter
來間接擷取和設定其它屬性setter
- 計算屬性一般隻提供
方法getter
- 如果隻提供
,而不提供getter
,則該計算屬性為隻讀屬性,并且可以省略setter
get{}
- 下面是計算屬性的寫法
- averageScore是計算屬性,通過chineseScore和mathScore計算而來的屬性
- 在setter方法中有一個newValue變量,是系統指定配置設定的
class Student {
// 存儲屬性
var age : Int = 0
var name : String?
var chineseScore : Double = 0.0
var mathScore : Double = 0.0
// 計算屬性
var averageScore : Double {
get {
return (chineseScore + mathScore) / 2
}
// 死循環,在内部又會調用set方法
// newValue是系統配置設定的變量名,内部存儲着新值
set {
self.averageScore = newValue
}
}
}
// 擷取計算屬性的值
print(stu.averageScore)
類屬性
- 類屬性是與類相關聯的,而不是與類的執行個體相關聯
- 所有的類和執行個體都共有一份類屬性.是以在某一處修改之後,該類屬性就會被修改
- 類屬性的設定和修改,需要通過類來完成
- 下面是類屬性的寫法
- 類屬性可以使用
來修飾static
- courseCount是類屬性,用來記錄學生有多少門課程
- 類屬性可以使用
class Student {
// 存儲屬性
var age : Int = 0
var name : String?
var chineseScore : Double = 0.0
var mathScore : Double = 0.0
// 計算屬性
var averageScore : Double {
return (chineseScore + mathScore) / 2
}
// 類屬性
static var englishScore:Double = 95.5
}
// 設定類屬性的值
Student.englishScore = 90.5
// 取出類屬性的值
print(Student.englishScore)
懶加載屬性
- 蘋果的設計思想:希望所有的對象在使用時才真正加載到記憶體中
- 在OC中我們可以重寫get方法來進行懶加載
- Swift用
關鍵字可以用于定義某一個屬性懶加載lazy
- lazy的作用是隻會指派一次
- 懶加載的本質是,在第一次使用的時候執行閉包,将閉包的傳回值指派給屬性
懶加載的使用
- 格式
lazy var 變量: 類型 = { 建立變量代碼 }()
- 案例
lazy var teacher:[String] = {
()->[String] in
return ["Mr Zhang", "Mr Li", "Mr Yang"]
}()
student.teacher
幾種屬性的差別
- 存儲屬性 —— 實實在在存儲常量和變量的
- 計算屬性 —— 依賴于存儲屬性,通過計算得出來,它提供getter和setter方法間接通路和設定值
- 類屬性 —— 本質是一個全局屬性,在類裡限定了其作用域,用關鍵字static修飾
- 懶加載屬性 —— 用關鍵字lazy修飾,必須進行初始化,非執行個體屬性懶加載時在大括号{}後面要加上()
- 全局屬性 —— 類外面的屬性,作用域全局
- 總結:
- 存儲屬性,最先被初始化
- 構造方法,僅次于存儲屬性調用,可以在這裡對存儲屬性進行指派
- 懶加載屬性、類屬性、全局屬性都是在第一次使用的時候初始化一次,以後調用都不再初始化
- 當懶加載屬性是基于一個存儲屬性計算的時候,切勿使用懶加載屬性,采用計算屬性
監聽屬性的改變
- 在OC中我們可以重寫set方法來監聽屬性的改變
- Swift中可以通過屬性觀察者來監聽和響應屬性值的變化
- 通常是監聽存儲屬性和類屬性的改變.(對于計算屬性,不需要定義屬性觀察者,因為可以在計算屬性的setter中直接觀察并響應這種值的變化)
- 定義觀察者
- willSet:在屬性值被存儲之前設定。此時新屬性值作為一個常量參數被傳入。該參數名預設為newValue,可以自定義
- didSet:在新屬性值被存儲後立即調用。與willSet相同,此時傳入的是屬性的舊值,預設參數名為oldValue,可以自定義
- willSet與didSet隻有在屬性改變時才會調用,在初始化時不會去調用這些監聽方法
class Student {
var name:String?{
// 屬性即将改變,還未改變時會調用的方法
// 可以給newValue自定義名稱
willSet(new){
print("willSet---")
// 在該方法中有一個預設的系統屬性newValue,用于存儲新值
if let new = new {
print(new)
}
}
// 屬性值已經改變了,會調用的方法
didSet{
print("didSet---")
// 在該方法中有一個預設的系統屬性oldValue,用于存儲舊值
if let oldValue = oldValue {
print(oldValue)
}
}
}
}
var student = Student()
// 在指派時,監聽該屬性的改變
student.name = "Zhangsan"
student.name = "Lisi"
屬性繼承與重寫
- 屬性繼承:子類可以繼承父類的屬性,包括存儲屬性、計算屬性和類型屬性,還可以繼承父類的屬性觀察器。
- 屬性重寫
- 無論繼承的是存儲屬性還是計算屬性,子類都可以通過提供getter和setter對屬性進行重寫
- 可以将一個繼承的屬性重寫為一個讀寫屬性
- 不可以将繼承來的讀寫屬性重寫為隻讀屬性
- 如果重寫時提供了setter方法,一定要提供getter方法
- 屬性觀察器重寫
- 無論父類有沒有為該屬性添加屬性觀察器,子類都可以添加屬性觀察器
- 如果父類已經添加了屬性觀察器,當屬性發生變化時,父類與子類都會得到通知
- 屬性觀察器不能用于計算屬性,隻能用于存儲屬性,因為計算屬性在setter裡就可以擷取到屬性的變化
執行個體方法
- 執行個體方法屬于特定類執行個體、結構體執行個體或者枚舉執行個體的函數
- 這裡的方法其實就是函數,隻不過放在類、結構體和枚舉中時稱之為方法
self 屬性
- 每一個類的執行個體都隐含一個叫做 self的屬性,可以使用 self通路目前類中的屬性和方法
class Student {
var str = "Hello, playground"
func say(info:String) {
print(info)
}
func eat(food:String){
//self指向的是目前類的執行個體
self.say(info: food)
print("吃\(food)")
}
}
var stu = Student()
stu.eat(food: "米飯")
值類型在執行個體方法中修改屬性和調用方法
- 值類型預設情況下,不能在執行個體方法中修改屬性
- 不能用self調用其他的函數
- 可以在函數前放一個
關鍵字來實作mutating
struct Student {
var str = "Hello, playground"
mutating func say(info:String) {
print(info)
self.str = "Hello World"
print(self.str)
}
mutating func eat(food:String){
self.say(info: food)
print("吃\(food)")
}
}
類型方法
- 在函數前使用 static關鍵字(能在類、結構體中使用)
- 在函數前使用 class關鍵字(隻能在類中使用)
static func play(){
print("play")
}
class func study(){
print("study")
}
class 和 static 總結
- class 和 static 相同點
- 可以修飾方法,static 修飾的方法叫做靜态方法,class修飾的叫做類方法
- 都可以修飾計算屬性
- class 和 static 不同點
- class 不能修飾存儲屬性,static 可以修飾存儲屬性,static修飾的存儲屬性稱為靜态變量(常量)
- class 修飾的計算屬性可以被重寫,static 修飾的不能被重寫
- static 修飾的靜态方法不能被重寫,class 修飾的類方法可以被重寫
- class 修飾的類方法被重寫時,可以使用static 讓方法變為靜态方法
- class 修飾的計算屬性被重寫時,可以使用static 讓其變為靜态屬性,但它的子類就不能被重寫了
- class 隻能在類中使用,但是static 可以在類,結構體,或者枚舉中使用