Static和class属性是属于类型而不是实例的属性。它们的历史是为了存储所有实例共享的信息(例如,计数器、配置、工厂)。在Swift中,static可以用于所有类型(class、struct、enum),而class仅可用于类,并且仅适用于可计算的属性,从而允许在继承中重写。
**问题:**错误使用静态属性可能导致竞争条件和来自不同线程的访问错误。static和class容易混淆,可能错误地选择继承中的重写机制。
解决办法:
代码示例:
class Counter { static var count = 0 static let queue = DispatchQueue(label: "counter.queue") static func increment() { queue.sync { count += 1 } } class var typeDescription: String { return "Generic Counter" } } class NamedCounter: Counter { override class var typeDescription: String { return "Named Counter" } }
关键特点:
问题1:能否将static let属性声明为计算属性(computed property)并带有get?
是的,static属性可以是存储的也可以是计算的。对于let属性,这通常是常量,但static var可以是计算的:
struct Math { static var pi: Double { return 3.1415926 } }
问题2:static var默认线程安全吗?
不,如果static var从不同线程修改,可能会出现竞争状态。读取/写入需要手动同步。
问题3:可以使用class var用于存储属性吗?
不,class var必须始终是计算属性(带有get/可选set),存储属性仅允许用于static。
在应用程序中,用户登录计数器存储在static var中,并在不同线程中未同步地增量。
优点:
缺点:
对于全局配置对象,使用static let,并且对它的访问仅限于读取或使用DispatchQueue进行写入。
优点:
缺点: