【问题标题】:Why property observer doesn't work with classes? [duplicate]为什么属性观察器不适用于类? [复制]
【发布时间】:2018-04-12 21:56:59
【问题描述】:

使用游乐场。

我有以下结构:

struct Foo {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

我将其中的一个实例声明为属性观察者,name 的默认值为“James”,age 的默认值为 33:

var myFoo = Foo(name: "James", age: 33) {
    willSet {
        print("my foo will be: \(newValue)")
    }
    didSet {
        print("my foo was: \(oldValue)")
    }
}

尝试编辑实例的name 时:

myFoo.name = "John"

我可以在日志上看到:

我的 foo 将是:Foo(name: "John", age: 33)

我的 foo 是:Foo(name: "James", age: 33)

这是我的期望。但是,当将Foo 声明为类而不是结构:class Foo 并运行完全相同的代码时,日志上不会出现任何内容。

背后的原因是什么?

【问题讨论】:

    标签: swift class struct property-observer


    【解决方案1】:

    因为类是引用类型,而结构是值类型。

    • 假设 Foo 是一个类。 myFoo 只是一个参考。说myFoo.name = "John" 会在原地改变对象; myFoo 没有分配新值,所以 setter 观察者没有什么可观察的。

    • 假设 Foo 是一个结构。那是一种价值类型。它不能原地变异。因此,说myFoo.name = "John" 实际上用一个新结构替换了变量myFoo 中的结构;设置变量并触发 setter 观察者。


    这也是为什么即使 myFoo 是用 let 声明的(即对象只是在原地发生变异),你也可以为一个类说 myFoo.name = "John",但你不能用结构来做到这一点——你必须用var 声明myFoo,以便可以替换变量值。

    【讨论】:

    • 感谢您的明确解释。所以更新Foo 实例的属性并不意味着实例本身已被重置。我想那是我的误会...
    • 另外,正如您在duplicated question 中提到的,如果我输入myFoo = Foo(name: "new", age: 101),我可以在日志中看到预期的结果。
    • 完全正确:对于一个类,除非您真正明确 将实例替换为另一个实例,否则您将看不到任何内容。但是结构不同:它隐式将实例替换为另一个实例,仅仅是因为您设置了一个属性。
    猜你喜欢
    • 2021-12-19
    • 2020-03-09
    • 2020-03-03
    • 2012-12-12
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 2011-12-23
    • 2016-01-08
    相关资源
    最近更新 更多