发布于 2015-06-14 01:58:16 | 199 次阅读 | 评论: 0 | 来源: 网络整理
实例的属性属于一个特定类型实例,每次类型实例化后都拥有自己的一套属性值,实例之间的属性相互独立。
也可以为类型本身定义属性,不管类型有多少个实例,这些属性都只有唯一一份。这种属性就是类型属性。
类型属性用于定义特定类型所有实例共享的数据,比如所有实例都能用的一个常量(就像 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"