[英]How to make array of protocol at the same time conform to Equatable?
以下代碼編譯沒有問題
protocol Animal {
}
var animals = [Animal]()
但是,我們有一個新要求,我們需要比較Animal
的數組
protocol Animal {
}
func x(a0: [Animal], a1: [Animal]) -> Bool {
return a0 == a1
}
var animals = [Animal]()
上面的代碼會產生編譯錯誤
協議'Animal'作為一種類型不能符合'Equatable'
我們傾向於修復
protocol Animal: Equatable {
}
func x(a0: [Animal], a1: [Animal]) -> Bool {
return a0 == a1
}
var animals = [Animal]()
在數組聲明行,我們收到錯誤
協議“Animal”只能用作通用約束,因為它具有 Self 或關聯的類型要求
我可否知道,
協議不能符合 Equatable。 原因是,它需要自我。 Self 指的是符合 Equatable 的具體(例如結構/類)類型。 如果您希望能夠對數組使用協議而不是具體類型,那么您需要自己編寫壓縮 function:
protocol Animal {
var name: String { get }
}
func compare(lhsAnimals: [Animal], rhsAnimals: [Animal]) -> Bool {
guard lhsAnimals.count == rhsAnimals.count else { return false}
for i in 0..<lhsAnimals.count {
if lhsAnimals[i].name != rhsAnimals[i].name {
return false
}
}
return true
}
Swift 的這一部分可能有點混亂,並且有改進的計划。
當您編寫類似a0: [Animal]
的內容時,您說您的 function 采用數組參數,其元素是協議存在( Animal
協議)。
存在的Animal
是一個 object,它讓用戶可以統一訪問Animal
協議的所有要求(屬性、方法、下標、初始化程序等),而不管底層符合 object( Cat
、 Dog
等)的具體類型如何。 )。
在 SE-0335 后的新世界中,您的代碼必須像這樣拼寫:
func x(a0: [any Animal], a1: [any Animal]) -> Bool {
return a0 == a1
}
問題變得更加清晰:不能保證a0
和a1
包含相同類型的動物。 它現在字面上寫在代碼中:它們是任何動物類型的 arrays。 每個都可以包含任何類型的動物,並且a0
與a1
中的動物類型之間沒有關系。 這是一個問題,因為Equatable
對其要求進行了特定的驗證:它的==
運算符僅適用於相同類型的兩個對象。
為了解決這個問題,您需要使您的 function 通用,以包含a0
和a1
以包含某些特定類型的對象:
func x<A: Animal>(a0: [A], a1: [A]) -> Bool {
return a0 == a1
}
感謝@Alexander 和他指出的視頻資源 - https://youtu.be/_m6DxTEisR8?t=2585
這是一個很好的解決方法,可以克服 Swift 協議的當前限制。
protocol Animal {
func isEqual(to: Animal) -> Bool
}
func isEqual(lhs: [Animal], rhs: [Animal]) -> Bool {
let count0 = lhs.count
let count1 = rhs.count
if count0 != count1 {
return false
}
for i in 0..<count0 {
if !(lhs[i].isEqual(to: rhs[i])) {
return false
}
}
return true
}
// struct. By conforming Equatable, struct is getting an auto
// implementation of "static func == (lhs: Dog, rhs: Dog) -> Bool"
struct Dog: Animal, Equatable {
func isEqual(to other: Animal) -> Bool {
guard let other = other as? Dog else { return false }
return self == other
}
}
// class
class Cat: Animal, Equatable {
static func == (lhs: Cat, rhs: Cat) -> Bool {
// TODO:
return true
}
func isEqual(to other: Animal) -> Bool {
guard let other = other as? Cat else { return false }
return self == other
}
}
var animals0 = [Animal]()
var animals1 = [Animal]()
// Instead of using
// if animals0 == animals1 {
// we will use the following function call
if isEqual(lhs: animals0, rhs: animals1) {
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.