在Swift中,为什么分配给静态变量也会调用其getter [英] In Swift, why does assigning to a static variable also invoke its getter

查看:73
本文介绍了在Swift中,为什么分配给静态变量也会调用其getter的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解到,在Swift中,静态var隐式地是惰性的: https://stackoverflow.com/a/34667272/1672161

I understand that in Swift, static vars are implicitly lazy: https://stackoverflow.com/a/34667272/1672161

但是我不清楚为什么会发生这种情况:

But I'm not clear on why this happens:

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

我看到的是,静态var的分配也在某种意义上调用了getter.这对我来说并不直观.这是怎么回事为什么作业不只发生?

What I'm seeing is that the assignment to the static var, is also invoking the getter in a sense. This isn't intuitive to me. What is happening here? Why doesn't the assignment only happen?

推荐答案

这是因为当前静态和全局存储的变量(这是 all 可能会更改)仅由编译器赋予一个访问器– unsafeMutableAddressor,它获取指向变量存储的指针(可以通过检查发出的SIL或IR来 /a>).

This is because static and global stored variables are currently (this is all subject to change) only given one accessor by the compiler – unsafeMutableAddressor, which gets a pointer to the variable's storage (this can be seen by examining the SIL or IR emitted).

此访问器:

  1. 获取指向编译器生成的全局标志的指针,该标志确定静态变量是否已初始化.

  1. Gets a pointer to a compiler-generated global flag determining whether the static variable has been initialised.

调用 swift_once 与该指针,以及用于初始化静态变量的函数(这是您为其赋予的初始化程序表达式,即= Hat()).在Apple平台上,swift_once只需转发到dispatch_once_f .

Calls swift_once with this pointer, along with a function that initialises the static variable (this is the initialiser expression you give it, i.e = Hat()). On Apple platforms, swift_once simply forwards onto dispatch_once_f.

返回一个指向静态变量存储的指针,由于存储具有静态寿命,因此调用者可以自由读取和修改该指针.

Returns a pointer to the static variable's storage, which the caller is then free to read and mutate – as the storage has static lifetime.

因此,它或多或少地等同于Objective-C线程安全的惰性初始化模式:

So it does more or less the equivalent of the Objective-C thread-safe lazy initialisation pattern:

+(Hat*) hat {

    static Hat* sharedHat = nil;
    static dispatch_once_t oncePredicate;

    dispatch_once(&oncePredicate, ^{
        sharedHat = [[Hat alloc] init];
    });

    return sharedHat;
}

主要区别在于,Swift会返回指向sharedHat存储的指针(指向引用的指针),而不是sharedHat 本身(只是对实例的引用).

The main difference being that Swift gives back a pointer to the storage of sharedHat (a pointer to a reference), rather than sharedHat itself (just a reference to the instance).

因为这是静态和全局存储变量的唯一访问器,所以为了执行赋值,Swift需要调用它以获取指向存储的指针.因此,如果尚未初始化-访问者需要先将其初始化为默认值(因为它不知道调用者将如何处理它),然后再设置调用者 then 改成另一个值.

Because this is the one and only accessor for static and global stored variables, in order to perform an assignment, Swift needs to call it in order to get the pointer to the storage. Therefore, if it wasn't initialised already – the accessor needs to first initialise it to its default value (as it has no idea what the caller is going to do with it), before the caller then sets it to another value.

此行为确实有些不直观,并且已被提交为错误.正如乔丹·罗斯(Jordan Rose)在报告评论中所说:

This behaviour is indeed somewhat unintuitive, and has been filed as a bug. As Jordan Rose says in the comments of the report:

这目前是设计使然,但可能值得更改设计.

This is currently by design, but it might be worth changing the design.

因此,这种行为很可能会在该语言的未来版本中发生改变.

So this behaviour could well change in a future version of the language.

这篇关于在Swift中,为什么分配给静态变量也会调用其getter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆