2017-08-28 1 views
0

ich eine Struktur Implementierung zusammengesetzt wie folgt:Falsche mehrere eingeschränkte Erweiterungen Implementierung genannt

protocol ProtocolA { 
    func doStuff() 
} 

protocol ProtocolB { } 

extension ProtocolA { 
    func doStuff() { 
    print("From protocol A") 
    } 
} 

extension ProtocolA where Self: ProtocolB { 
    func doStuff() { 
    print("From protocol B") 
    } 
} 

Und ich habe die folgenden Klassen:

class MyClassA: ProtocolA { 
    func letsDoSomething() { 
     self.doStuff() 
    } 
} 

class MyClassB: MyClassA, ProtocolB { 
} 

Was passiert ist:

let ia = MyClassA() 
ia.letsDoSomething() // From protocol A (OK!) 

let ib = MyClassB() 
ib.letsDoSomething() // From protocol A (Wrong!) 

Natürlich erwarte ich nicht, die zweite Antwort zu haben.

Wie in der Swift Programming Launguage Anleitung angegeben:

Wenn ein konformer Typ die Anforderungen für mehr eingeschränkten Erweiterungen erfüllt, die Implementierungen für die gleiche Methode oder Eigenschaft bieten, wird Swift die Umsetzung zu den speziellen Einschränkungen entsprechend verwenden.

Warum die Klasse ib, die ProtocolB konform ist die spezialisierteste Erweiterung Implementierung nicht nennen ist?

Ich weiß, dass die anrufende Klasse noch MyClassA ist aber, da die Instanz von MyClassB ist, die das Protokoll entsprechen ProtocolB Ich erwarte, dass nach wie vor die meisten spezialisierten Implementierung haben aufgerufen werden.

+0

Vergleich Punkt # 2 von https://stackoverflow.com/a/42286148/2976878 und https://stackoverflow.com/a/44706021/2976878. 'MyClassB' erhält keine eigene Konformität zu 'ProtocolA'; Es basiert auf der Konformität von 'MyClassA'. – Hamish

+0

Ich stimme zu, deshalb erwarte ich als Ergebnis '\\ Von Protokoll B'. Stimmst du nicht zu? –

+1

Nein; 'MyClassB' beruht auf der Übereinstimmung von 'MyClassA' mit' ProtocolA'. 'MyClassA' stimmt nicht mit' ProtocolB' überein, daher kann die Constrained-Extension-Methode ihre Konformität nicht erfüllen. Daher erfüllt die unbeschränkte Erweiterungsmethode ihre Konformität und ist daher diejenige, die aufgerufen wird. – Hamish

Antwort

1

Das Problem ist, dass MYClassB von MyClass A geerbt wird. Swifts Methodenversandregeln diese Implementierung der untergeordneten Klasse wird nie aufgerufen und die Standardimplementierung wird immer im Falle der Protokollkonformität verwendet. Versuchen Sie, den gleichen Fall wie diese

class MyClassA: ProtocolA { 
    func letsDoSomething() { 
     self.doStuff() 
    } 
} 

class MyClassB: ProtocolA, ProtocolB { 
} 


let ia = MyClassA() 
ia.letsDoSomething() // From protocol A (OK!) 

let ib = MyClassB() 
ib.doStuff() // From protocol A (Wrong!) 
+0

Das Problem besteht darin, genau die Implementierung von 'letsFoSomething' zu verwenden, die bereits in' MyClassA' implementiert ist, aber das Verhalten von 'doStuff()' durch Verwendung der eingeschränkten Implementierung von 'extension ProtocolA wobei Self: ProtocolB' ersetzt wurde. Im Anschluss an Ihre Lösung muss ich den freigegebenen Code in "LestDoSomething" kopieren und einfügen. Ich bin mir nicht sicher, ob ich den Punkt richtig erklärt habe. Ist das klar? Haben Sie eine Idee, wie dies erreicht werden kann, ohne die Implementierung von 'ia.letsDoSomething()' zu kopieren? –

Verwandte Themen