verwendet werden Ich möchte eine Klasse mit statischen Initialisierungsmethode haben:‚Self‘ kann nicht in nicht-trivialen Verschlüsse
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()
}
}
Leider ist Swift 3-Compiler nicht in der Lage Art für jede Schließung komplexer als { self.init() }
schließen . Zum Beispiel:
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()
}
Jeder Versuch, Verschlusstyp, Variablentyp explizit oder Guss A
-Self
führt zu einem Fehler angeben:
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'
}
Die Lösung ist Schließungen zu vermeiden Self
verwenden.
Dies scheint wie eine sehr unglückliche Einschränkung des Compilers. Gibt es einen Grund dafür? Wird dieses Problem wahrscheinlich in zukünftigen Swift-Versionen behoben?
Obwohl nicht identisch, ist dies sehr ähnlich zu http://stackoverflow.com/questions/25645090/Protokoll-Func-Rückkehr-Selbst. Das grundlegende Problem besteht darin, dass Swift den Kompilierertyp selbst bestimmen muss, aber zur Laufzeit bestimmen will. Es wurde etwas erweitert, damit Klassenfunktionen Self ausführen können, wenn alles zur Kompilierungszeit aufgelöst werden kann, aber Swift kann nicht immer beweisen, dass Ihre Typen * in einigen dieser Fälle korrekt sein müssen (manchmal weil es nicht weiß, wie noch, und manchmal, weil es tatsächlich möglich ist, falsch zu liegen). –
Ich erwarte, dass dies ein wenig besser wird, aber Swift entmutigt diese Art von komplexer Vererbung (das sind nicht endgültige Klassen, also müssen Sie alle möglichen Unterklassen berücksichtigen) und bevorzugt Protokolle langfristig, also würde ich das nicht erwarten in Swift 4 oder 5 vollständig möglich sein. –
@RobNapier _Swift kann nicht immer beweisen, dass Ihre Typen in einigen dieser Fälle korrekt sein müssen (manchmal weil es noch nicht weiß, und manchmal, weil es tatsächlich möglich ist, falsch zu liegen) Gibt es Beispiele für solche Fälle? –