Überschreibung der Protokoll-Standardimplementierung in einer Sub-Unterklasse nimmt nicht am dynamischen Versand teil [duplizieren]

8

Betrachte folgenden Spielplatz:

%Vor%

Ich verstehe nicht, warum a.f() und b.f() return "AAAA" - sie sollen "CCCC" zurückgeben, weil func f() -> String dynamisch gesendet werden sollte (wie im Protokoll deklariert).

Wenn ich class B so ändere, dass es so aussieht:

%Vor%

dann alle drei Aufrufe an .f() return "CCCC" wie erwartet.

Ich glaube, es ist ein Fehler im Swift-Compiler, ich habe Xcode 7.3.1 und 8.0-beta3 eingecheckt, dieses Verhalten ist in beiden reproduzierbar.

Ist das tatsächlich ein erwartetes Verhalten?

    
Oleksii Taran 17.08.2016, 23:53
quelle

1 Antwort

4

Sie sind hier einige Regeln beteiligt.

Manchmal wird die statische Verteilung verwendet (in diesem Fall müssen wir uns den Typ von var / let ansehen, um herauszufinden, welche Implementierung verwendet wird).

Zu anderen Zeiten wird stattdessen dynamischer Versand verwendet (dies bedeutet, dass die Implementierung des Objekts innerhalb der Variablen verwendet wird).

Betrachten wir das allgemeine Beispiel

%Vor%
  

Ich werde die folgenden Definitionen verwenden

     
  • classic implementation of f() , um anzuzeigen, wenn f () außerhalb einer Protokollerweiterung definiert ist (also innerhalb einer Struktur / Klasse).

  •   
  • default implementation of f() , um anzugeben, ob f() in einer Protokollerweiterung definiert ist.

  •   

Dynamischer Versand

Wenn SomeType1 ein struct/class mit seiner eigenen "klassischen" Implementierung von f() ist, dann wird Polymorphismus angewendet .

Wenn SomeType2 keine klassische Implementierung von f() hat, wird SomeType1.f() verwendet. Andernfalls gewinnt SomeType2.f() .

Static Dispatch

Wenn SomeType1 keine klassische Implementierung von f() hat, aber eine Standardimplementierung hat, dann ist Polymorphismus ausgeschaltet .

In diesem Fall wird die Standardimplementierung des Typs let/var gewonnen.

a.

Schauen wir uns Ihr erstes Beispiel an

%Vor%

In diesem A gibt es keine eigene klassische Implementierung (weil es keine Struktur / Klasse ist), sondern eine Standardimplementierung. Daher ist Polymorphismus ausgeschaltet und A.f() wird verwendet.

b.

Gleiche Regel für Ihr zweites Beispiel

%Vor%

B hat keine klassische Implementierung von f (), hat aber eine Standardimplementierung von f() . Daher ist Polymorphismus ausgeschaltet und B.f() (von der Protokollerweiterung) wird verwendet.

c.

Schließlich ist das Objekt vom Typ C innerhalb einer Konstante vom Typ C .

%Vor%

Hier hat C eine klassische Implementierung von f() . In diesem Fall wird die Protokollimplementierung ignoriert und C.f() verwendet.

Mehr

Sehen wir uns ein anderes Beispiel an

%Vor%

Wie Sie sehen, gewinnt der Typ der Konstante, die den Wert enthält, wieder. Und wenn Sie das Foo Objekt in eine Foo Konstante setzen, erhalten Sie einen Kompilierungsfehler

%Vor%     
Luca Angeletti 18.08.2016, 00:26
quelle

Tags und Links