簡體   English   中英

如何使協議數組同時符合 Equatable?

[英]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 或關聯的類型要求

我可否知道,

  1. 為什么我們可以在協議符合 Equatable 之前有一個協議數組?
  2. 為什么一旦協議符合 Equatable,我們就不允許有協議數組?
  3. 有什么好的方法可以解決此類錯誤?

協議不能符合 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( CatDog等)的具體類型如何。 )。

在 SE-0335 后的新世界中,您的代碼必須像這樣拼寫:

func x(a0: [any Animal], a1: [any Animal]) -> Bool {
    return a0 == a1
}

問題變得更加清晰:不能保證a0a1包含相同類型的動物。 它現在字面上寫在代碼中:它們是任何動物類型的 arrays。 每個都可以包含任何類型的動物,並且a0a1中的動物類型之間沒有關系。 這是一個問題,因為Equatable對其要求進行了特定的驗證:它的==運算符僅適用於相同類型的兩個對象。

為了解決這個問題,您需要使您的 function 通用,以包含a0a1以包含某些特定類型的對象:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM