Swift5.1—类型属性

简介: Swift5.1—类型属性

实例属性属于一个特定类型的实例,每创建一个实例,实例都拥有属于自己的一套属性值,实例之间的属性相互独立。


你也可以为类型本身定义属性,无论创建了多少个该类型的实例,这些属性都只有唯一一份。这种属性就是类型属性


类型属性用于定义某个类型所有实例共享的数据,比如所有实例都能用的一个常量(就像 C 语言中的静态常量),或者所有实例都能访问的一个变量(就像 C 语言中的静态变量)。


存储型类型属性可以是变量或常量,计算型类型属性跟实例的计算型属性一样只能定义成变量属性。


注意

跟实例的存储型属性不同,必须给存储型类型属性指定默认值,因为类型本身没有构造器,也就无法在初始化过程中使用构造器给类型属性赋值。

存储型类型属性是延迟初始化的,它们只有在第一次被访问的时候才会被初始化。即使它们被多个线程同时访问,系统也保证只会对其进行一次初始化,并且不需要对其使用 lazy 修饰符。


类型属性语法


在 C 或 Objective-C 中,与某个类型关联的静态常量和静态变量,是作为 global(全局)静态变量定义的。但是在 Swift 中,类型属性是作为类型定义的一部分写在类型最外层的花括号内,因此它的作用范围也就在类型支持的范围内。


使用关键字 static 来定义类型属性。在为类定义计算型类型属性时,可以改用关键字 class 来支持子类对父类的实现进行重写。下面的例子演示了存储型和计算型类型属性的语法:


struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 1
    }
}
enum SomeEnumeration {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 6
    }
}
class SomeClass {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    class var overrideableComputedTypeProperty: Int {
        return 107
    }
}


注意

例子中的计算型类型属性是只读的,但也可以定义可读可写的计算型类型属性,跟计算型实例属性的语法相同。


获取和设置类型属性的值


跟实例属性一样,类型属性也是通过点运算符来访问。但是,类型属性是通过类型本身来访问,而不是通过实例。比如:


print(SomeStructure.storedTypeProperty)
// 打印“Some value.”
SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty)
// 打印“Another value.”
print(SomeEnumeration.computedTypeProperty)
// 打印“6”
print(SomeClass.computedTypeProperty)
// 打印“27”


下面的例子定义了一个结构体,使用两个存储型类型属性来表示两个声道的音量,每个声道具有 010 之间的整数音量。


下图展示了如何把两个声道结合来模拟立体声的音量。当声道的音量是 0,没有一个灯会亮;当声道的音量是 10,所有灯点亮。本图中,左声道的音量是 9,右声道的音量是 7


2466108-f5d04ab04883727e.webp.jpg


上面所描述的声道模型使用 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 的存储型实例属性,表示当前声道现在的音量,取值为 010


属性 currentLevel 包含 didSet 属性观察器来检查每次设置后的属性值,它做如下两个检查:


  • 如果 currentLevel 的新值大于允许的阈值 thresholdLevel,属性观察器将 currentLevel 的值限定为阈值 thresholdLevel
  • 如果修正后的 currentLevel 值大于静态类型属性 maxInputLevelForAllChannels 的值,属性观察器就将新值保存在 maxInputLevelForAllChannels 中。


注意

在第一个检查过程中,didSet 属性观察器将 currentLevel 设置成了不同的值,但这不会造成属性观察器被再次调用。


可以使用结构体 AudioChannel 创建两个声道 leftChannelrightChannel,用以表示立体声系统的音量:


var leftChannel = AudioChannel()
var rightChannel = AudioChannel()


如果将左声道的 currentLevel 设置成 7,类型属性 maxInputLevelForAllChannels 也会更新成 7


leftChannel.currentLevel = 7
print(leftChannel.currentLevel)
// 输出“7”
print(AudioChannel.maxInputLevelForAllChannels)
// 输出“7”


如果试图将右声道的 currentLevel 设置成 11,它会被修正到最大值 10,同时 maxInputLevelForAllChannels 的值也会更新到 10


rightChannel.currentLevel = 11
print(rightChannel.currentLevel)
// 输出“10”
print(AudioChannel.maxInputLevelForAllChannels)
// 输出“10”


目录
相关文章
|
6月前
|
存储 Swift iOS开发
在Swift编程语言中,集合类型`Set`
在Swift编程语言中,集合类型`Set`
55 2
|
10天前
|
Swift 索引 容器
Swift 泛型-扩展泛型类型
Swift 泛型-扩展泛型类型
18 2
|
10天前
|
Swift 索引
Swift 泛型-类型约束
Swift 泛型-类型约束
20 1
|
14天前
|
存储 监控 Swift
Swift 属性
10月更文挑战第29天
24 2
|
18天前
|
安全 Swift iOS开发
Swift 可选(Optionals)类型
10月更文挑战第24天
32 2
|
6月前
|
存储 安全 Swift
【Swift开发专栏】Swift中的集合类型:数组、字典与集合
【4月更文挑战第30天】本文探讨Swift的三种内置集合类型:数组、字典和集合。数组是有序元素集合,支持动态大小调整和类型安全;字典是无序键值对,适用于快速查找;集合是无序不重复元素集合,适合检查元素存在性和集合运算。理解这些特性和用法能提升Swift编程效率。
69 1
|
5月前
|
存储 Swift
Swift开发——属性检查器
Swift中的属性检查器(willSet, didSet)允许在设置存储属性值前后执行代码。在类`Circle`中,属性`radius`使用属性观察器:willSet在赋值前检查值,若值为负则打印警告;didSet在赋值后比较新旧值,根据变化输出相应信息。在实例`c`中,`radius`从-5变为0时,输出“Input value is negative.”和“The circle gets smaller.”;从0变为10时,输出“Input value is normal.”和“The circle gets larger.”。
215 4
Swift开发——属性检查器
|
5月前
|
存储 程序员 Swift
Swift开发——存储属性与计算属性
Swift推荐使用结构体进行开发,结构体支持属性和方法,且作为值类型。结构体属性包括存储属性(如radius)和计算属性(如r),计算属性不存储值,类似方法。结构体用`struct`定义,命名遵循大驼峰规则。实例名遵循小驼峰规则。属性可在结构体中任意位置定义,静态属性用`static`。存储属性可为`lazy`实现懒加载。结构体实例通过`.`访问属性和方法,静态属性和方法用`结构体名.`访问。计算属性可读写,可通过`get`和`set`定义。程序段1展示了结构体Point和Circle的属性和方法,包括私有属性、只读计算属性、可读写计算属性及`mutating`方法。
40 0
Swift开发——存储属性与计算属性
|
6月前
|
安全 Swift
【Swift开发专栏】Swift中的可选类型与解包
【4月更文挑战第30天】Swift的可选类型(Optional)用于表示变量可能无值,如用户未填写表单或空服务器数据。可选类型用问号(?)标记,状态可为包含值或nil。解包包括强制解包(!,可能触发运行时错误)、可选绑定(在if/while中安全解包)和隐式解包(声明时带!,使用时不需显式解包)。高级用法包括可选链式调用、空合并操作符(??)和可选类型比较。理解并恰当使用这些概念能提升代码的健壮性和安全性。
66 1
|
6月前
|
安全 Swift iOS开发
【Swift开发专栏】Swift中的属性观察者与KVO
【4月更文挑战第30天】Swift编程语言支持属性观察者(`willSet`和`didSet`)和键值观察(KVO)来响应属性变化。属性观察者在设置前(`willSet`)和设置后(`didSet`)执行代码,可用于数据绑定。KVO是Cocoa/Cocoa Touch中的机制,需`NSObject`子类和`@objc dynamic`属性配合使用。注意在观察者销毁前移除观察,以避免内存问题。示例展示了属性观察者实现简单数据绑定。
85 1