Swift: Self.init 在初始化程序中调用了多次
Swift: Self.init called multiple times in initializer
这个让我难住了。我不明白为什么 Swift 抱怨 self.init 在此代码中被多次调用:
public init(body: String) {
let parser = Gravl.Parser()
if let node = parser.parse(body) {
super.init(document: self, gravlNode: node)
} else {
// Swift complains with the mentioned error on this line (it doesn't matter what "whatever" is):
super.init(document: self, gravlNode: whatever)
}
}
除非我遗漏了什么,否则很明显它只调用了一次 init
。有趣的是,如果我注释掉第二行 Swift 抱怨 Super.init 没有在所有路径上调用,哈哈。
我错过了什么?
更新:
好的,所以问题肯定是试图在对 super.init 的调用中传递 self
。我完全忘记了我在做那件事,哈。我想我已经实验性地编写了它并对其进行了编译,并认为它可能确实有效,但看起来 it's actually a bug 它完全是以这种方式编译的。
无论如何,由于将 self
传递给初始化程序有点多余,因为它是同一个对象,我更改了父初始化程序以接受可选的文档参数(它只是一个内部初始化程序,所以没什么大不了的)并且如果它是 nil
我只是在父初始值设定项中将它设置为 self
。
对于那些好奇的人,这是父初始化程序(现在)的样子:
internal init(document: Document?, gravlNode: Gravl.Node) {
self.value = gravlNode.value
super.init()
self.document = document ?? self as! Document
// other stuff...
}
我怀疑这是一个错误的诊断(即错误的错误消息)。如果您有一个我们可以试验的完整示例,那将非常有帮助,但这一行没有意义(我怀疑是潜在的问题):
super.init(document: self, gravlNode: node)
您不能将 self
传递给 super.init
。你还没有初始化(你在调用 super.init
之前还没有初始化)。例如,考虑以下简化代码:
class S {
init(document: AnyObject) {}
}
class C: S {
public init() {
super.init(document: self)
}
}
这导致 error: 'self' used before super.init call
我认为这是正确的错误。
编辑:我相信 Hamish 确实发现了一个编译器错误。您可以在 Xcode 8.3.1 中以这种方式利用它(尚未在 8.3.2 上测试过):
class S {
var x: Int
init(document: S) {
self.x = document.x
}
}
class C: S {
public init() {
super.init(document: self)
}
}
let c = C() // malloc: *** error for object 0x600000031244: Invalid pointer dequeued from free list
这个让我难住了。我不明白为什么 Swift 抱怨 self.init 在此代码中被多次调用:
public init(body: String) {
let parser = Gravl.Parser()
if let node = parser.parse(body) {
super.init(document: self, gravlNode: node)
} else {
// Swift complains with the mentioned error on this line (it doesn't matter what "whatever" is):
super.init(document: self, gravlNode: whatever)
}
}
除非我遗漏了什么,否则很明显它只调用了一次 init
。有趣的是,如果我注释掉第二行 Swift 抱怨 Super.init 没有在所有路径上调用,哈哈。
我错过了什么?
更新:
好的,所以问题肯定是试图在对 super.init 的调用中传递 self
。我完全忘记了我在做那件事,哈。我想我已经实验性地编写了它并对其进行了编译,并认为它可能确实有效,但看起来 it's actually a bug 它完全是以这种方式编译的。
无论如何,由于将 self
传递给初始化程序有点多余,因为它是同一个对象,我更改了父初始化程序以接受可选的文档参数(它只是一个内部初始化程序,所以没什么大不了的)并且如果它是 nil
我只是在父初始值设定项中将它设置为 self
。
对于那些好奇的人,这是父初始化程序(现在)的样子:
internal init(document: Document?, gravlNode: Gravl.Node) {
self.value = gravlNode.value
super.init()
self.document = document ?? self as! Document
// other stuff...
}
我怀疑这是一个错误的诊断(即错误的错误消息)。如果您有一个我们可以试验的完整示例,那将非常有帮助,但这一行没有意义(我怀疑是潜在的问题):
super.init(document: self, gravlNode: node)
您不能将 self
传递给 super.init
。你还没有初始化(你在调用 super.init
之前还没有初始化)。例如,考虑以下简化代码:
class S {
init(document: AnyObject) {}
}
class C: S {
public init() {
super.init(document: self)
}
}
这导致 error: 'self' used before super.init call
我认为这是正确的错误。
编辑:我相信 Hamish 确实发现了一个编译器错误。您可以在 Xcode 8.3.1 中以这种方式利用它(尚未在 8.3.2 上测试过):
class S {
var x: Int
init(document: S) {
self.x = document.x
}
}
class C: S {
public init() {
super.init(document: self)
}
}
let c = C() // malloc: *** error for object 0x600000031244: Invalid pointer dequeued from free list