2015-07-18 6 views
19

Kann ich Protokollkonformität über eine schnelle Erweiterung zu einem Protokoll hinzufügen?Swift 2 Protokollkonformität zu Protokollen hinzufügen

//Plain old protocol here 
protocol MyData { 
    var myDataID: Int { get } 
} 

Ich mag das MyData Protokoll gleichzusetzen standardmäßig machen (nur die ID-Vergleich)

extension MyData : Equatable { } 

Aber ich habe diesen schönen Fehler:

"Extension of protocol 'MyData' cannot have an inheritance clause"

Das Verhalten ich suche BananaData entspricht Equatable (einem Protokoll), da es das MyData-Protokoll implementiert, das eine Standardimplementierung von Equalable

bereitstellen kann
//This is the method to implement Equatable 
func ==(lhs: MyData, rhs: MyData) -> Bool { 
    return lhs.myDataID == rhs.myDataID 
} 

struct BananaData: MyData { 
    var myDataID: Int = 1 
} 

func checkEquatable(bananaOne: BananaData, bananaTwo: BananaData) { 
    //This compiles, verifying that BananaData can be compared 
    if bananaOne == bananaTwo { } 
    //But BananaData is not convertible to Equatable, which is what I want 
    let equatableBanana = bananaOne as Equatable 
    //I don't get the additional operations added to Equatable (!=) 
    if bananaOne != bananaTwo { } //Error 
} 

Antwort

23

Wie die Fehlermeldung sagt: eine Erweiterung eines Protokolls kann keine Vererbungsklausel haben. Stattdessen könnten Sie MyData Protokoll erben von Equatable in der ursprünglichen Deklaration.

protocol MyData: Equatable { 
    var myDataID: Int { get } 
} 

Sie dann eine Implementierung von == für Typen hinzufügen erweitern könnte, die MyData entsprechen:,

func == <T: MyData>(lhs: T, rhs: T) -> Bool { 
    return lhs.myDataID == rhs.myDataID 
} 

jedoch Ich würde das sehr nicht empfehlen! Wenn Sie konformen Typen weitere Eigenschaften hinzufügen, werden ihre Eigenschaften nicht auf Gleichheit überprüft. Nehmen Sie das folgende Beispiel:

struct SomeData: MyData { 
    var myDataID: Int 
    var myOtherData: String 
} 

let b1 = SomeData(myDataID: 1, myOtherData: "String1") 
let b2 = SomeData(myDataID: 1, myOtherData: "String2") 

b1 == b2 // true, although `myOtherData` properties aren't equal. 

Im obigen Fall müssen Sie == für SomeData für das korrekte Ergebnis außer Kraft zu setzen, damit die == machen, dass MyData überflüssig akzeptiert.

+0

Kleinen Follow-up zu verstehen, hatte ich angenommen, dass wer auch immer umgesetzt 'MyData' muss auch gleichzusetzen explizit implementieren. Z.B. Die Implementierung von Equatable ist eine Voraussetzung für MyData (was ich vermeiden wollte). Die 'BananaData' sind natürlich ein beigesteuertes Beispiel, aber danke für die Warnung. – Kevin

2

Spielt dieser Spielplatz was Sie wollen? Ich machte es auf dem, was ich von Protocol-Oriented Programming in Swift von WWDC 2015.

import Foundation 

//Plain old protocol here 

func == (lhs: MyData, rhs: MyData) -> Bool { 
    return lhs.myDataID == rhs.myDataID 
} 

func != (lhs: MyData, rhs: MyData) -> Bool { 
    return lhs.myDataID != rhs.myDataID 
} 

protocol MyData { 
    var myDataID: Int { get } 
} 

extension MyData where Self: Equatable { 

} 


struct BananaData: MyData { 
    var myDataID: Int = 1 
} 

func checkEquatable(bananaOne: BananaData, bananaTwo: BananaData) { 
    //This compiles, verifying that BananaData can be compared 
    if bananaOne == bananaTwo { 
     print("Same") 
    } 
    //But BananaData is not convertible to Equatable, which is what I want 
    //I don't get the additional operations added to Equatable (!=) 
    print(bananaOne.myDataID) 
    print(bananaTwo.myDataID) 


    if bananaOne != bananaTwo { 

    } 

    //Error 


} 

let b1 = BananaData(myDataID: 2) 
let b2 = BananaData(myDataID: 2) 

checkEquatable(b1, bananaTwo: b2) 

let c = b1 == b2 // Evaluates as true 
+0

Wenn eine Struktureigenschaft mit Equatable übereinstimmt (mit '=='), erhalten Sie automatisch die Funktion '! ='. Ich habe '! =' Verwendet, um zu überprüfen, ob 'BananaData' tatsächlich dem' Equatable'-Protokoll entspricht, anstatt nur eine '==' -Methode zu haben. Also, während dies für meinen Testfall kompiliert wurde, war das, was ich wirklich suchte, eine Möglichkeit, 'Equatable' für alle' MyData' Strukturen zu implementieren. – Kevin

+2

Hallo @ Kevin. Ich weiß nicht, ob das einen Unterschied macht, aber ich sehe, dass du einen Fehler bekommst, wenn du das machst ... 'extension MyData: Equatable {}' aber du bekommst keinen Fehler, wenn du eine eingeschränkte Protokollerweiterung wie diese machst 'extension MyData wo Self: Gleichstellbar {}' – Vader