Swift拡張機能を介してプロトコル適合性をプロトコルに追加できますか?
//Plain old protocol here
protocol MyData {
var myDataID: Int { get }
}
MyData
プロトコルをデフォルトで同等にしたい(IDを比較するだけ)
extension MyData : Equatable { }
しかし、私はこの素敵なエラーを受け取ります:
「プロトコル「MyData」の拡張に継承句を含めることはできません」
私が探している動作は、Equatable(プロトコル)に準拠したBananaDataです。これは、Equatableのデフォルトの実装を提供できるMyDataプロトコルを実装しているためです。
//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
}
エラーメッセージにあるように、プロトコルの拡張には継承句を含めることはできません。代わりに、元の宣言のMyData
からEquatable
プロトコルを継承させることができます。
protocol MyData: Equatable {
var myDataID: Int { get }
}
次に、MyData
に準拠する型の==
の実装を拡張して追加できます。
func == <T: MyData>(lhs: T, rhs: T) -> Bool {
return lhs.myDataID == rhs.myDataID
}
ただし、これは強くお勧めしません!適合型にさらにプロパティを追加すると、それらのプロパティが等しいかどうかはチェックされません。以下の例を見てください。
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.
上記の場合、正しい結果を得るには、SomeData
の==
をオーバーライドする必要があります。これにより、MyData
を受け入れる==
が冗長になります。
この遊び場はあなたが望むことをしますか?私は、WWDC 2015の Swiftでのプロトコル指向プログラミング から理解したことに基づいて作成しました。
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