2016-07-12 21 views
3
protocol A { 
    func f() 
} 

struct S1 : A { 
    func f() { 
     print("S1") 
    } 
} 

struct S2 : A { 
    func f() { 
     print("S2") 
    } 
} 

let array: [A] = [S1(), S2()] 

for s: A in array { 
    s.f() 
} 

// "S1\n" "S2\n" 

Wenn dies eine Vererbungshierarchie wäre, würde ich Swift erwarten, eine v-Tabelle zu verwenden, um die korrekte Implementierung nachzuschlagen. Die konkreten Typen in array könnten jedoch alles sein, was A zusammen mit einer beliebigen Anzahl anderer Protokolle implementiert. Wie also würde die Swift-Laufzeit die Struktur des Objekts kennen, wenn es auch v-Tabellen verwendet?Woher weiß Swift zur Laufzeit, welche Implementierung verwendet werden soll?

+1

Swift verwendet eine "Protocol Witness Table", um dies zu tun - diese WWDC-Diskussion erklärt es ziemlich gut: https://developer.apple.com/videos/play/wwdc2016-416/?time=1474 – Hamish

+0

Ehrfürchtig, und witzig genug, ich hatte schon vor, dieses Video heute zu sehen. :) –

+0

War im Begriff zu antworten, aber ja, schau dir das an :) –

Antwort

1

Die Swift-Laufzeit verwendet eine Protokoll-Witness-Tabelle, die Zeiger auf die Implementierungen der Protokollmethoden jedes Typs enthält.

Mike Ash erklärt es am besten in seinem Artikel Exploring Swift Memory Layout, Part II:

die letzte, bei Offset 32 ​​ein „Protokoll Zeuge Tabelle“ für den zugrunde liegenden Typ ist und das Protokoll, die Zeiger auf den Typ der Implementierungen enthält der die Protokollmethoden. Auf diese Weise kann der Compiler Methoden wie p() für einen Wert des Protokolltyps aufrufen, ohne den zugrunde liegenden Typ zur Laufzeit zu kennen.

Ich würde auch das WWDC Video sehen Understanding Swift Performance wie in den Kommentaren von Hamish vorgeschlagen.