我不知道我是否太累了,但我认为还有更多。 (我尝试了两杯咖啡,但仍然无法解决问题......)
我想从外部创建一个只读变量,但可以通过方法写入。 (所以在那个例子中我可以确保favoriteNumber只是一位数。
(我不想让它成为计算属性并在get {}中设置{},因为在我的其他项目中我想根据与set {的“newValue”不同的值修改变量})
struct Person {
var name: String
private(set) var favoriteNumber: Int? // Should only be single-digit
init(name: String, number: Int) {
self.name = name
// Make sure favorite number is single-digit
guard number >= 0 && number < 10 else {
self.favoriteNumber = nil
}
self.favoriteNumber = number
}
func changeFavoriteNumber(number: Int) {
guard number >= 0 && number < 10 else { return }
self.favoriteNumber = number
}
}
该行
self.favoriteNumber = number
中的函数
changeFavoriteNumber(number:)
引发错误
"Cannot assign to property: 'self' is immutable"
并建议“Mark方法'改变'以使'自我'可变”。但这不是我想要的,因为我不想修改Person类型的实例,而是一个可变变量...( var favoriteNumber)
假设以这种方式使用:
let frank = Person.init(name: "Frank", number: 9)
frank.changeFavoriteNumber(number: 8)
我不知道这里发生了什么(即使现在有3个咖啡:)
答案 0 :(得分:3)
如果您不想使用mutating
,则必须Person
class
而不是struct
。后者不允许突变,除非方法标记为mutable
且实例是var
变量而不是let
变量。
为了完整起见,我还提到了使用struct
解决此问题的方法,但我建议不要使用此解决方法。你可以&#34; box&#34;另一个(引用类型)对象中的属性值;这样你就可以伪装变异。像这样:
class Box<T> {
var value: T
init(_ value: T) { self.value = value }
}
struct Person {
private var favoriteNumber: Box<Int> = Box(0)
func changeFavoriteNumber(_ number: Int) {
self.favoriteNumber.value = number
}
}
现在,您可以使用Person
访问favoriteNumber.value
内的值。
答案 1 :(得分:3)
结构是值类型,并且具有与类不同的语义。存储类实例的变量被存储为对存储器中其他地方的实际对象的引用;这意味着你可以有两个指向同一个对象的变量,你可以修改一个类的成员,无论引用它的变量是否可变。
结构是不同的。存储struct
实例的变量直接存储结构的成员,而不是作为对其他地方的对象的引用。这意味着将结构传递给函数或另一个变量会创建它的副本,并且修改struct
会直接修改存储它的变量。
因此,结构是不可变的,除非它存储在var
中。必须根据编译器的建议将变形结构的函数声明为mutating
,以便编译器可以强制只在let
结构上调用非变异函数。
答案 2 :(得分:1)
你不应该以与思考类相同的方式来思考结构。 swift中的结构具有价值语义。您无法更改使用let定义的结构的任何属性。尽管结构中的属性是用var定义的,因为origin是用let定义的。
例如: 现在你可以这样做:
frank.favoriteNumber = 10
但是如果你想改变一个结构的属性,因为它引用了值语义,你必须使用你的函数进行变异。变异,因为您正在改变结构的属性。 试试这个 变化:
mutating func changeFavoriteNumber(number: Int) {
guard number >= 0 && number < 10 else { return }
self.favoriteNumber = number
}
var frank = Person.init(name: "Frank", number: 9)
frank.changeFavoriteNumber(number: 8)
来自苹果文档:
从实例方法中修改值类型 结构和枚举是值类型。默认情况下,无法在其实例方法中修改值类型的属性。 但是,如果需要在特定方法中修改结构或枚举的属性,则可以选择改变该方法的行为。然后,该方法可以从方法中改变(即更改)其属性,并且当方法结束时,它所做的任何更改都将写回原始结构。该方法还可以为其隐式self属性分配一个全新的实例,并且该新实例将在方法结束时替换现有实例。 您可以通过将mutating关键字放在该方法的func关键字之前来选择此行为: URL