Swift编程语言学习11—— 枚举全局变量、局部变量与类型属性
全局变量和局部变量
计算属性和属性监视器所描写叙述的模式也能够用于全局变量和局部变量,全局变量是在函数、方法、闭包或不论什么类型之外定义的变量,局部变量是在函数、方法或闭包内部定义的变量。
前面章节提到的全局或局部变量都属于存储型变量,跟存储属性类似,它提供特定类型的存储空间,并同意读取和写入。
另外,在全局或局部范围都能够定义计算型变量和为存储型变量定义监视器,计算型变量跟计算属性一样,返回一个计算的值而不是存储值,声明格式也全然一样。
注意:
全局的常量或变量都是延迟计算的,跟延迟存储属性相似,不同的地方在于,全局的常量或变量不须要标记@lazy特性。
局部范围的常量或变量不会延迟计算。
类型属性
实例的属性属于一个特定类型实例,每次类型实例化后都拥有自己的一套属性值,实例之间的属性相互独立。
也能够为类型本身定义属性,无论类型有多少个实例,这些属性都仅仅有唯一一份。这样的属性就是类型属性。
类型属性用于定义特定类型全部实例共享的数据,比方全部实例都能用的一个常量(就像 C 语言中的静态常量),或者全部实例都能訪问的一个变量(就像 C 语言中的静态变量)。
对于值类型(指结构体和枚举)能够定义存储型和计算型类型属性,对于类(class)则仅仅能定义计算型类型属性。
值类型的存储型类型属性能够是变量或常量,计算型类型属性跟实例的计算属性一样定义成变量属性。
注意:
跟实例的存储属性不同,必须给存储型类型属性指定默认值,由于类型本身无法在初始化过程中使用构造器给类型属性赋值。
类型属性语法
在 C 或 Objective-C 中,静态常量和静态变量的定义是通过特定类型加上globalkeyword。在 Swift 编程语言中,类型属性是作为类型定义的一部分写在类型最外层的花括号内,因此它的作用范围也就在类型支持的范围内。
使用keywordstatic来定义值类型的类型属性,keywordclass来为类(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) // 输出 "Somevalue." SomeStructure.storedTypeProperty ="Another value." println(SomeStructure.storedTypeProperty) // 输出 "Anothervalue.”
以下的样例定义了一个结构体,使用两个存储型类型属性来表示多个声道的声音电平值,每一个声道有一个 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"