因爲Equatable
有Self
的要求,所以不應該直接在協議上實現。否則,該協議將作爲一種類型不可用。
要在協議級別實現Equatable
,但能夠使用該協議作爲類型,則可以使用類型擦除。
爲了演示,我修改了您的操場中給出的代碼來構建橡皮擦。
因爲我使用的方法的詳細說明,請參閱這個職位上我的博客:
https://khawerkhaliq.com/blog/swift-protocols-equatable-part-two/
這裏是你的遊樂場修改後的代碼:
protocol CustomProtocol {
var title: String { get }
var subtitle: String { get }
func isEqualTo(_ other: CustomProtocol) -> Bool
func asEquatable() -> AnyEquatableCustomProtocol
}
extension CustomProtocol where Self: Equatable {
func isEqualTo(_ other: CustomProtocol) -> Bool {
guard let o = other as? Self else { return false }
return self == o
}
func asEquatable() -> AnyEquatableCustomProtocol {
return AnyEquatableCustomProtocol(self)
}
}
struct A: CustomProtocol, Equatable {
var title: String
var subtitle: String
static func ==(lhs: A, rhs: A) -> Bool {
return lhs.title == rhs.title && lhs.subtitle == rhs.subtitle
}
}
struct B: CustomProtocol, Equatable {
var title: String
var subtitle: String
static func ==(lhs: B, rhs: B) -> Bool {
return lhs.title == rhs.title && lhs.subtitle == rhs.subtitle
}
}
struct AnyEquatableCustomProtocol: CustomProtocol, Equatable {
var title: String { return value.title }
var subtitle: String { return value.subtitle }
init(_ value: CustomProtocol) { self.value = value }
private let value: CustomProtocol
static func ==(lhs: AnyEquatableCustomProtocol, rhs: AnyEquatableCustomProtocol) -> Bool {
return lhs.value.isEqualTo(rhs.value)
}
}
// instances typed as the protocol
let a: CustomProtocol = A(title: "First title", subtitle: "First subtitle")
let b: CustomProtocol = B(title: "First title", subtitle: "First subtitle")
let equalA: CustomProtocol = A(title: "First title", subtitle: "First subtitle")
let unequalA: CustomProtocol = A(title: "Second title", subtitle: "Second subtitle")
// equality tests
print(a.asEquatable() == b.asEquatable()) // prints false
print(a.asEquatable() == equalA.asEquatable()) // prints true
print(a.asEquatable() == unequalA.asEquatable()) // prints false
點需要注意的是,通過這種方法,實際的==
比較被委託給底層的具體類型,但我們只處理協議類型以維護抽象。
在這裏,我只使用了擦除類型的實例來進行一次比較。但是,由於類型橡皮擦符合CustomProtocol
,因此可以在任何需要協議類型的地方保存和使用這些實例。因爲它們符合Equatable
,所以它們也可以用於任何需要符合要求的地方。
只是爲了背景下,這篇文章解釋了爲什麼這是不可取的嘗試直接在協議執行Equatable
一致性,甚至==
功能:
https://khawerkhaliq.com/blog/swift-protocols-equatable-part-one/
因此,類型擦除。
希望這會有所幫助。
您需要從更新的協議聲明中刪除相等函數,因爲它們只在擴展中需要。 – Ollie
比較https://stackoverflow.com/q/41298464/2976878 – Hamish