Ich frage mich, ob es möglich ist, so etwas zu erreichen.
Ich habe einen Spielplatz wie diesen:
protocol Foo {
func testPrint()
}
extension Foo {
func testPrint() {
print("Protocol extension call")
}
}
struct Bar: Foo {
func testPrint() {
// Calling self or super go call default implementation
self.testPrint()
print("Call from struct")
}
}
let sth = Bar()
sth.testPrint()
Ich kann eine Standardimplementierung in bereitstellen, extension
aber was ist, wenn Bar
alles benötigt wird, was in der Standardimplementierung enthalten ist, sowie zusätzliche Dinge?
Es ist irgendwie ähnlich wie das Aufrufen von super.
Methoden in class
es, um die Anforderung der Implementierung jeder Eigenschaft usw. zu erfüllen, aber ich sehe keine Möglichkeit, dasselbe mit zu erreichen structs
.
Foo.testPrint(self)()
- das Problem ist, dass es aufgrund eines Segmentierungsfehlers (getestet auf 7.0 GM und 7.1 Beta) fehlschlägtAntworten:
Ich weiß nicht, ob Sie noch nach einer Antwort darauf suchen, aber Sie können die Funktion aus der Protokolldefinition entfernen, Ihr Objekt umwandeln
Foo
und dann die Methode darauf aufrufen:protocol Foo { // func testPrint() <- comment this out or remove it } extension Foo { func testPrint() { print("Protocol extension call") } } struct Bar: Foo { func testPrint() { print("Call from struct") (self as Foo).testPrint() // <- cast to Foo and you'll get the default // function defined in the extension } } Bar().testPrint() // Output: "Call from struct" // "Protocol extension call"
Aus irgendeinem Grund funktioniert es nur, wenn die Funktion nicht als Teil des Protokolls deklariert ist, sondern in einer Erweiterung des Protokolls definiert ist. Stelle dir das vor. Aber es funktioniert.
quelle
Foo
Protokoll kein anderes Protokoll erbt.Nun, Sie könnten einen verschachtelten Typ erstellen, der dem Protokoll entspricht, ihn instanziieren und die Methode für diesen aufrufen (es spielt keine Rolle, dass Sie nicht auf die Daten Ihres Typs zugreifen können, da die Implementierung in der Protokollerweiterung sowieso nicht darauf verweisen kann). Aber es ist keine Lösung, die ich als elegant bezeichnen würde.
struct Bar: Foo { func testPrint() { // Calling default implementation struct Dummy : Foo {} let dummy = Dummy() dummy.testPrint() print("Call from struct") } }
quelle
Danke für den Beitrag! Wenn Sie die Funktionsdefinition in das Protokoll einfügen, wird beim Umwandeln des Objekts als Protokoll nur die Version der Funktion des Objekts angezeigt, und da Sie es in sich selbst aufrufen, erhalten Sie die neue Adresse von Apple ...
Ich habe eine Version wie diese ausprobiert:
import UIKit protocol MyProc { } protocol MyFuncProc { func myFunc() } extension MyProc { func myFunc() { print("Extension Version") } } struct MyStruct: MyProc, MyFuncProc { func myFunc() { print("Structure Version") (self as MyProc).myFunc() } } (MyStruct() as MyFuncProc).myFunc()
Dies ergibt eine Ausgabe von:
Structure Version Extension Version
quelle
Wenn Ihr Protokoll hat
associatedType
oderSelf
Anforderungen, dann wird die Besetzung nicht. Um dies zu umgehen, erstellen Sie eine "Schatten" -Standardimplementierung, die sowohl von der regulären Standardimplementierung als auch vom konformen Typ aufgerufen werden kann.protocol Foo { associatedType Bar } extension Foo { func testPrint() { defaultTestPrint() } } fileprivate extension Foo { // keep this as private as possible func defaultTestPrint() { // default implementation } } struct Bar: Foo { func testPrint() { // specialized implementation defaultTestPrint() } }
quelle
defaultXX()
ist viel ausdrucksvoller und lesbarer als andere Antworten.Was denkst du über eine solche Art, dies zu beheben?
protocol Foo { func testPrint() } extension Foo { func testPrint() { defaultTestPrint() } func defaultTestPrint() { print("Protocol extension call") } } struct Bar: Foo { func testPrint() { // Calling self or super go call default implementation defaultTestPrint() print("Call from struct") } } let sth = Bar() sth.testPrint()
quelle