我经常发现自己喜欢在struct
,enum
和protocol
的初始化程序中编写self = someValue
之类的东西。当我有一些预定义值或正在克隆现有值时,这非常好。
但是,此语法不适用于class
。我也不知道为什么。
如果您担心双重初始化,则Swift编译器会知道我是否在何时,何处调用了指定的super
或self
初始化程序,因此它知道我是否已完成对该实例的初始化。
如果担心我还没有调用指定的初始化器,那应该没问题,因为我只是将此实例作为对另一个实例的引用(2个vars 1指针)。
如果担心并发访问可能导致self
已经被初始化,那么这是无稽之谈,因为我们位于初始化器和Swift initializers are not susceptible to that中。
毕竟,我发现我可以通过一次使用的协议解决这个问题:
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!
那么为什么通常不使用此协议,却在协议扩展中允许使用它呢?
答案 0 :(得分:3)
这似乎当前表现正常。
整个问题已在快速论坛上进行了讨论:Assigning to Self in Protocol Extensions
上次在内部讨论中出现这个怪癖时,我们中的一些人认为,可能有必要禁止类完全符合带有变更需求的协议。如果您考虑一下,这在某种程度上是有道理的-似乎很难编写可同时在可变值和可变引用上操作的代码,因为后者不具有值语义:
var x = y x.mutatingProtocolRequirement() // did y change too?
但是,讨论最终失败了。