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作为答案?