Swift類型屬性
類型屬性
實例的屬性屬於一個特定類型實例,每次類型實例化後都擁有自己的一套屬性值,實例之間的屬性相互獨立。
也可以爲類型本身定義屬性,不管類型有多少個實例,這些屬性都只有唯一一份。這種屬性就是類型屬性。
類型屬性用於定義特定類型所有實例共享的數據,比如所有實例都能用的一個常量(就像 C 語言中的靜態常量),或者所有實例都能訪問的一個變量(就像 C 語言中的靜態變量)。
對於值類型(指結構體和枚舉)可以定義存儲型和計算型類型屬性,對於類(class)則只能定義計算型類型屬性。
值類型的存儲型類型屬性可以是變量或常量,計算型類型屬性跟實例的計算屬性一樣定義成變量屬性。
注意:
跟實例的存儲屬性不同,必須給存儲型類型屬性指定默認值,因爲類型本身無法在初始化過程中使用構造器給類型屬性賦值。
類型屬性語法
在 C 或 Objective-C 中,靜態常量和靜態變量的定義是通過特定類型加上global
關鍵字。在 Swift 編程語言中,類型屬性是作爲類型定義的一部分寫在類型最外層的花括號內,因此它的作用範圍也就在類型支持的範圍內。
使用關鍵字static
來定義值類型的類型屬性,關鍵字class
來爲類(class)定義類型屬性。下面的例子演示了存儲型和計算型類型屬性的語法:
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
// 這裏返回一個 Int 值
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
// 這裏返回一個 Int 值
}
}
class SomeClass {
class var computedTypeProperty: Int {
// 這裏返回一個 Int 值
}
}
注意:
例子中的計算型類型屬性是隻讀的,但也可以定義可讀可寫的計算型類型屬性,跟實例計算屬性的語法類似。
獲取和設置類型屬性的值
跟實例的屬性一樣,類型屬性的訪問也是通過點運算符來進行,但是,類型屬性是通過類型本身來獲取和設置,而不是通過實例。比如:
println(SomeClass.computedTypeProperty)
// 輸出 "42"
println(SomeStructure.storedTypeProperty)
// 輸出 "Some value."
SomeStructure.storedTypeProperty = "Another value."
println(SomeStructure.storedTypeProperty)
// 輸出 "Another value.」
下面的例子定義了一個結構體,使用兩個存儲型類型屬性來表示多個聲道的聲音電平值,每個聲道有一個 0 到 10 之間的整數表示聲音電平值。
後面的圖表展示瞭如何聯合使用兩個聲道來表示一個立體聲的聲音電平值。當聲道的電平值是 0,沒有一個燈會亮;當聲道的電平值是 10,所有燈點亮。本圖中,左聲道的電平是 9,右聲道的電平是 7。
上面所描述的聲道模型使用AudioChannel
結構體來表示:
struct AudioChannel {
static let thresholdLevel = 10
static var maxInputLevelForAllChannels = 0
var currentLevel: Int = 0 {
didSet {
if currentLevel > AudioChannel.thresholdLevel {
// 將新電平值設置爲閥值
currentLevel = AudioChannel.thresholdLevel
}
if currentLevel > AudioChannel.maxInputLevelForAllChannels {
// 存儲當前電平值作爲新的最大輸入電平
AudioChannel.maxInputLevelForAllChannels = currentLevel
}
}
}
}
結構AudioChannel
定義了 2 個存儲型類型屬性來實現上述功能。第一個是thresholdLevel
,表示聲音電平的最大上限閾值,它是一個取值爲 10 的常量,對所有實例都可見,如果聲音電平高於 10,則取最大上限值 10(見後面描述)。
第二個類型屬性是變量存儲型屬性maxInputLevelForAllChannels
,它用來表示所有AudioChannel
實例的電平值的最大值,初始值是 0。
AudioChannel
也定義了一個名爲currentLevel
的實例存儲屬性,表示當前聲道現在的電平值,取值爲 0 到 10。
屬性currentLevel
包含didSet
屬性監視器來檢查每次新設置後的屬性值,有如下兩個檢查:
- 如果
currentLevel
的新值大於允許的閾值thresholdLevel
,屬性監視器將currentLevel
的值限定爲閾值thresholdLevel
。 - 如果修正後的
currentLevel
值大於任何之前任意AudioChannel
實例中的值,屬性監視器將新值保存在靜態屬性maxInputLevelForAllChannels
中。
注意:
在第一個檢查過程中,didSet
屬性監視器將currentLevel
設置成了不同的值,但這時不會再次調用屬性監視器。
可以使用結構體AudioChannel
來創建表示立體聲系統的兩個聲道leftChannel
和rightChannel
:
var leftChannel = AudioChannel()
var rightChannel = AudioChannel()
如果將左聲道的電平設置成 7,類型屬性maxInputLevelForAllChannels
也會更新成 7:
leftChannel.currentLevel = 7
println(leftChannel.currentLevel)
// 輸出 "7"
println(AudioChannel.maxInputLevelForAllChannels)
// 輸出 "7"
如果試圖將右聲道的電平設置成 11,則會將右聲道的currentLevel
修正到最大值 10,同時maxInputLevelForAllChannels
的值也會更新到 10:
rightChannel.currentLevel = 11
println(rightChannel.currentLevel)
// 輸出 "10"
println(AudioChannel.maxInputLevelForAllChannels)
// 輸出 "10"