我知道在 Swift 中,静态变量是隐式惰性的:https://stackoverflow.com/a/34667272/1672161
但我不清楚为什么会发生这种情况:
protocol HatType {}
class Hat: HatType {
init() { print("real hat") }
}
class MockHat: HatType {
init() { print("mock hat") }
}
struct HatInjector {
static var hat: HatType = Hat()
}
HatInjector.hat = MockHat()
// Output:
// real hat
// mock hat
我看到的是,对静态变量的赋值在某种意义上也调用了 getter。这对我来说并不直观。这里发生了什么?为什么任务不只发生?
这是因为静态和全局存储变量当前是(这是all可能会发生变化)编译器仅给出一个访问器 –unsafeMutableAddressor
,它获取指向变量存储的指针(这可以看出通过检查发出的 SIL 或 IR).
该访问器:
获取指向编译器生成的全局标志的指针,确定静态变量是否已初始化。
Calls swift_once使用此指针以及初始化静态变量的函数(这是您给它的初始化表达式,即= Hat()
)。在苹果平台上,swift_once
simply 转发到dispatch_once_f.
返回指向静态变量存储的指针,调用者可以自由读取和更改该指针,因为存储具有静态生命周期。
所以它或多或少相当于 Objective-C 线程安全的延迟初始化模式:
+(Hat*) hat {
static Hat* sharedHat = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
sharedHat = [[Hat alloc] init];
});
return sharedHat;
}
主要区别在于 Swift 返回一个指向存储的指针sharedHat
(指向引用的指针),而不是sharedHat
itself(只是对实例的引用)。
因为这就是那一个and only静态和全局存储变量的访问器,为了执行赋值,Swift 需要调用它来获取指向存储的指针。因此,如果它尚未初始化 - 访问器需要在调用者之前首先将其初始化为其默认值(因为它不知道调用者将用它做什么)then将其设置为另一个值。
这种行为确实有些不直观,并且已经被归档为错误。正如乔丹·罗斯在报告评论中所说:
目前这是设计使然,但可能值得更改设计。
因此,这种行为很可能会在该语言的未来版本中发生变化。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)