Swift ';自我';不能在非平凡闭包中使用
我想要一个具有静态初始化方法的类:Swift ';自我';不能在非平凡闭包中使用,swift,Swift,我想要一个具有静态初始化方法的类: class A { required init() { } // this one works class func f0() -> Self { return self.init() } // this one works as well class func f1() -> Self { let create = { self.init() } // no error, inferr
class A {
required init() {
}
// this one works
class func f0() -> Self {
return self.init()
}
// this one works as well
class func f1() -> Self {
let create = { self.init() } // no error, inferred closure type is '() -> Self'
return create()
}
}
不幸的是,Swift 3编译器无法为任何比{self.init()}
更复杂的闭包推断类型。例如:
class func f2() -> Self {
let create = {
// error: unable to infer complex closure return type; add explicit type to disambiguate
let a = self.init()
return a
}
return create()
}
任何明确指定闭包类型、变量类型或从A
转换为Self
的尝试都会导致错误:
class func f3() -> Self {
let create = { () -> Self in // error: 'Self' is only available in a protocol or as the result of a method in a class;
let a = self.init()
return a
}
return create()
}
class func f4() -> Self {
let create = {
let a: Self = self.init() // error: 'Self' is only available in a protocol or as the result of a method in a class;
return a
}
return create()
}
class func f5() -> Self {
let create = { () -> A in
let a = self.init()
return a
}
return create() as! Self // error: cannot convert return expression of type 'A' to return type 'Self'
}
解决方案是使用Self
避免闭包
这似乎是编译器的一个非常不幸的限制。这背后有什么原因吗?这个问题可能在未来的Swift版本中得到解决吗?基本问题是Swift需要在编译时确定Self的类型,但您希望在运行时确定它。它在某种程度上进行了扩展,允许类函数在编译时返回Self,但Swift不能总是证明您的类型在某些情况下必须是正确的(有时因为它还不知道如何返回,有时因为它实际上可能是错误的)
作为一个例子,考虑一个不重写自返回方法的子类。它如何返回子类?如果它把自我传递给其他东西呢?在编译器甚至不知道未来的子类的情况下,如何在编译时进行静态类型检查?(包括可在运行时和跨模块边界添加的子类。)
<>我希望这能更好一点,但是斯威夫特会阻止这种复杂的继承(这是非最终的类,所以你必须考虑所有可能的子类)并且更喜欢长期的协议,所以我不希望在SWIFT 4或5中完全可以这样做。基本问题是Swift需要在编译时确定
Self
的类型,但您希望在运行时确定它。它在某种程度上进行了扩展,允许类函数在编译时自行运行,但Swift不能总是证明您的类型在某些情况下必须是正确的(有时是因为它还不知道如何进行,有时是因为它实际上可能是错的)。我希望这会有所改善,但是Swift阻止了这种复杂的继承(这是非最终的类,所以你必须考虑所有可能的子类),并且更喜欢长期的协议,所以我不希望在SWIFT 4或5中完全有可能。@ RabpabySwift不能总是证明在某些情况下你的类型必须正确。(有时是因为它还不知道怎么做,有时是因为它实际上可能是错的)有没有这样的例子呢?当然。考虑一个不重写自返回方法的子类。它如何返回子类?如果它通过自我到其他什么?如果给定编译器不知道的未来子类,如何在编译时静态地检查?(包括可以在运行时和跨模块边界添加的子类。)@RobNapier Post作为答案?