2015-10-07 3 views
6

ich den Titel dieser Frage wissen, ist verwirrend, aber das seltsame Verhalten wird im folgenden Beispiel erläutert:In Swift, warum Unterklasse Methode, um die man nicht außer Kraft setzen kann, in übergeordnete Klasse von Protokollerweiterung zur Verfügung gestellt

protocol Protocol { 
    func method() -> String 
} 

extension Protocol { 
    func method() -> String { 
     return "From Base" 
    } 
} 

class SuperClass: Protocol { 
} 

class SubClass: SuperClass { 
    func method() -> String { 
     return "From Class2" 
    } 
} 

let c1: Protocol = SuperClass() 
c1.method() // "From Base" 
let c2: Protocol = SubClass() 
c2.method() // "From Base" 

Wie kommt c1.method() und c2.method() zurück dasselbe? Wie funktioniert die method() in SubClass nicht?

Interessanterweise ohne die Art der c2 erklärt, dies funktionieren wird:

let c2 = SubClass() 
c2.method() // "From Class2" 
+0

nette Frage. Ich habe ein ähnliches unter http: // stackoverflow.com/questions/33702738/Methode-Anpassung-in-Unterklasse-nicht-angerufen;). Welches ist möglicherweise ein Duplikat von Ihnen. Es ist so, als ob der dynamische Versand nur funktionieren kann, wenn die SuperClass die Funktion implementiert. – bm842

Antwort

0

Ich bin nicht ganz sicher, ob der zugrunde liegenden Mechanismus, aber es muss etwas sein, mit der Tatsache zu tun, dass don-Protokolle‘ t muss zwangsläufig eine Vererbung ermöglichen.

Ein Weg, um dieses Problem zu umgehen ist, indem auch die Methode Zugabe zu SuperClass

import Foundation 
protocol Protocol: class { 
    func method() -> String 
} 

extension Protocol { 
    func method() -> String { 
     return "From Base" 
    } 
} 

class SuperClass: Protocol { 
    func method() -> String { 
     return "From Super" 
     } 
} 

class SubClass: SuperClass { 
    override func method() -> String { 
     return "From Class2" 
    } 
} 

let c1: Protocol = SuperClass() 
c1.method() // "From Super" 
let c2: Protocol = SubClass() 
c2.method() // "From Class2" 
+0

ja es ist ein Workaround. Ich war nur neugierig, warum es nicht funktioniert, wenn es keine Implementierung in SuperClass – aquajach

0

Grundsätzlich ja, wenn es eine übergeordneten Klasse ist, die das Protokoll entspricht, bietet jedoch keine Implementierung für es, die Die Implementierung der Protokollerweiterung wird in Unterklassen verfügbar sein, auch wenn die Unterklassen implementiert sind (sie müssen jedoch in den Typ der Oberklasse oder des Protokolls umgewandelt werden).

Wenn jedoch die Superklasse eine Implementierung der Protokollmethode hat, ist die Implementierung des Protokolls weder von der Oberklasse noch von den Unterklassen verfügbar.

+0

Vielen Dank für die Antwort gibt. Wenn SubClass keine Unterklasse von SuperClass ist, sondern nur dem Protokoll entspricht, wie "class SubClass: Protocol {}". Dann lass c2: Protocol = SubClass(), c2.method() // Aus Class2, auch wenn ich c2 als Protokoll verwende. Meine aktuelle Schlussfolgerung ist, dass "Unterklassen Super-Klassen-Methoden, die von Erweiterungen des Protokolls bereitgestellt werden, nicht überschreiben können". – aquajach

+0

@aquajach Gute Beobachtung, ich schrieb meine Antwort danach um. –

1

Das Problem ist, dass c1 und c2 vom Typ Protocol sind, da Sie ihren Typ explizit auf diese Weise definiert haben (denken Sie daran: Protokolle sind vollwertige Typen). Dies bedeutet, dass Swift beim Aufruf method()Protocol.method aufruft.


Wenn Sie etwas definieren, wie:

let c3 = SuperClass() 

... c3 ist vom Typ SuperClass. Da SuperClass keine genauere method() Deklaration hat, wird Protocol.method() immer noch verwendet, wenn c3.method() aufgerufen wird.


Wenn Sie etwas definieren, wie:

let c4 = SubClass() 

... c4 ist vom Typ SubClass. Da SubClass eine genauere method() Deklaration hat, wird SubClass.method() verwendet, wenn c4.method() aufgerufen wird.


Sie könnten auch c2 bekommen SubClass.method() zu nennen, von unten Guss es `SubClass:

(c2 as! SubClass).method() // returns "From Class2" 

Hier ist eine Demonstration auf SwiftStub.

+1

danke für die Antwort. Ich füge SubClass2 (entspricht dem Protokoll direkt) und c5 auf http://swiftstub.com/452669817/?v=beta hinzu. Sie sehen, wenn c5 Protokoll direkt nicht über Vererbung oder Super-Klasse entspricht, selbst wenn ich c5 als Protokoll ausspreche, wird es immer noch die Methodenimplementierung von SubClass2 anstelle der Standard-Protokollerweiterung verwenden. Es ist einfach nicht sehr intuitiv für mich. – aquajach

Verwandte Themen