为什么Swift不允许在类初始化中不允许分配给self,而在协议初始化中不允许呢?

时间:2019-01-18 22:17:20

标签: swift initialization pass-by-reference pass-by-value initializer

我经常发现自己喜欢在structenumprotocol的初始化程序中编写self = someValue之类的东西。当我有一些预定义值或正在克隆现有值时,这非常好。

但是,此语法不适用于class。我也不知道为什么。 如果您担心双重初始化,则Swift编译器会知道我是否在何时,何处调用了指定的superself初始化程序,因此它知道我是否已完成对该实例的初始化。 如果担心我还没有调用指定的初始化器,那应该没问题,因为我只是将此实例作为对另一个实例的引用(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!

那么为什么通常不使用此协议,却在协议扩展中允许使用它呢?

1 个答案:

答案 0 :(得分:3)

这似乎当前表现正常。

整个问题已在快速论坛上进行了讨论:Assigning to Self in Protocol Extensions

  

上次在内部讨论中出​​现这个怪癖时,我们中的一些人认为,可能有必要禁止类完全符合带有变更需求的协议。如果您考虑一下,这在某种程度上是有道理的-似乎很难编写可同时在可变值和可变引用上操作的代码,因为后者不具有值语义:

var x = y
x.mutatingProtocolRequirement()
// did y change too?
     

但是,讨论最终失败了。