gup*_*ron 6 variables static lazy-evaluation swift
据我所知,在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
Run Code Online (Sandbox Code Playgroud)
我所看到的是,对静态var的赋值也在某种意义上调用了getter.这对我来说并不直观.这里发生了什么?为什么这项任务不会发生?
这是因为静态和全局存储变量当前(这一切都可以改变)只有编译器给出一个访问器 - unsafeMutableAddressor它获得一个指向变量存储的指针(这可以通过检查发出的SIL或IR来看到).
这个访问者:
获取指向编译器生成的全局标志的指针,该标志确定静态变量是否已初始化.
swift_once使用此指针调用,以及初始化静态变量的函数(这是您给它的初始化表达式,即= Hat()).在Apple平台上,swift_once只需转发到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;
}
Run Code Online (Sandbox Code Playgroud)
主要区别在于Swift返回指向存储sharedHat(指向引用的指针)的指针,而不是sharedHat 自身(仅仅是对实例的引用).
因为这是静态和全局存储变量的唯一访问器,为了执行赋值,Swift需要调用它以获取指向存储的指针.因此,如果它尚未初始化-存取需要先将其初始化为它的默认值(因为它不知道来电者是打算用它做),调用者之前,然后将其设置为另一个值.
这种行为确实有些不直观,并且已经被归档为bug.正如乔丹·罗斯在报告的评论中所说:
目前这是设计,但可能值得改变设计.
所以这种行为很可能在未来的语言版本中发生变化.