Sup*_*tar 5 initialization initializer pass-by-reference pass-by-value swift
我经常发现自己喜欢在structs、enums 和protocols 的初始化器中如何编写类似self = someValue. 当我有一些预定义值或克隆现有值时,这非常有用。
然而,这个语法对 es 不起作用class。我也实在想不通为什么。
无法赋值:“self”是不可变的
如果关注的是双重初始化,Swift 编译器知道我是否、何时以及在何处调用指定super或self初始化器,因此它知道我是否已完成初始化该实例。如果担心的是我还没有调用指定的初始化程序,那么应该没问题,因为我只是让这个实例成为对另一个实例的引用(2 vars 1 指针)。如果担心的是并发访问可能导致self已经被初始化...那么这是无意义的,因为我们在初始化器中,而Swift 初始化器不易受此影响。
毕竟我发现我可以通过一次性协议来解决这个问题:
class MyClass {
let content: String
init(content: String) {
self.content = content
}
convenience init(from1 other: MyClass) {
self = other // Cannot assign to value: 'self' is immutable
}
}
protocol MyProto {}
extension MyClass: MyProto {}
extension MyProto {
init(from2 other: Self) {
self = other
}
}
let foo = MyClass(content: "Foo")
print(MyClass(from1: foo)) // Never would've compiled in the first place
print(MyClass(from2: foo)) // Perfectly OK!
Run Code Online (Sandbox Code Playgroud)
那么为什么这在普通用法中被拒绝,但在协议扩展中被允许呢?
看来目前的表现符合预期。
\n\n整个问题已经在 swift 论坛上讨论过:Assigning to Self in Protocol Extensions
\n\n\n\n上次在内部讨论中出现这个怪癖时,我们中的一些人的想法是,完全禁止类遵守具有变异要求的协议可能是值得的。如果您考虑一下,这有一定道理 \xe2\x80\x94 似乎很难编写可以对可变值和可变引用进行操作的代码,因为后者没有值语义:
\n\nRun Code Online (Sandbox Code Playgroud)\n\nvar x = y\nx.mutatingProtocolRequirement()\n// did y change too?\n然而讨论却以失败告终。
\n