arrays - 为什么数组不符合 Equatable,而它的项在 Swift 中是 Equatable 的?

标签 arrays swift generics swift3 enums

更新:

从包含 Swift 4.1 的 Xcode 9.3 开始,数组相等性按预期工作,原始问题中的代码编译没有错误。

但是,请查看已接受的答案,因为它提供了更好、更现代的解决方案。

原题如下:


当我尝试声明类型为 [Post] 的通用枚举实例时,我收到一条错误消息

Type '[Post]' does not conform to protocol 'Equatable'

这是无稽之谈,因为 Post符合 Equatable我实际上可以比较两个 [Post]没有编译错误的实例?


在下面的示例中,我扩展了 PostResult<T>类型为 Equatable然后我做了一些测试:

  1. 测试我可以比较两个 Post类型:OK
  2. 测试我可以比较两个 [Post]类型:OK
  3. 测试我可以比较两个 Result<Post>类型:OK
  4. 测试我可以比较两个 Result<[Post]>类型:错误
import Foundation

struct Post {
    let text: String
}
extension Post: Equatable {}
func ==(lhs: Post, rhs: Post) -> Bool {
    return lhs.text == rhs.text
}


enum Result<T: Equatable> {
    case success(result: T)
    case error
}
extension Result: Equatable {
    static func ==(lhs: Result<T>, rhs: Result<T>) -> Bool {
        switch (lhs, rhs) {
        case let (.success(lhsVal), .success(rhsVal)):
            return lhsVal == rhsVal
        case (.error, .error):
            return true
        default:
            return false
    }
}

func test() {

    // Test 1: Check Post type for equality: OK
    let post1: Post = Post(text: "post 1")
    let post2: Post = Post(text: "post 2")

    if post1 == post2 {
        print("equal posts")
    }

    // Test 2: Check [Post] type for equality: OK
    let arrayOfPosts1: [Post] = [ post1, post2 ]
    let arrayOfPosts2: [Post] = [ post1, post2 ]

    if arrayOfPosts1 == arrayOfPosts2 {
        print("equal arrays of post")
    }

    // Test 3: Check Result<Post> type for equality: OK
    let result1: Result<Post> = Result<Post>.success(result: post1)
    let result2: Result<Post> = Result<Post>.success(result: post2)

    if result1 == result2 {
        print("equal results of post")
    }

    // Test 4: Check Result<[Post]> type for equality: ERROR
    // Compiler error: "Type '[Post]' does not conform to protocol 'Equatable'"
    let arrayResult1: Result<[Post]> = Result<[Post]>.success(result: arrayOfPosts1)
    let arrayResult2: Result<[Post]> = Result<[Post]>.success(result: arrayOfPosts2)

    if arrayResult1 == arrayResult2 {
        print("equal results of array of posts")
    }
}

最佳答案

Swift 4.1 更新:

随着在 Swift 4.1 中引入条件一致性,Array 现在符合 Equatable,因此应该可以解决该问题,而无需诉诸任何变通方法。

此外,Swift 现在允许类型自动合成 Equatable 一致性,前提是其所有成员都是 Equatable,只需将 Equatable 一致性声明为原始类型定义的一部分(不是扩展)但没有实现其任何要求。这适用于提供关联值(如果有)是 Equatable 的枚举。

这个问题的代码现在可以更简洁地写成如下:

import Foundation

struct Post: Equatable {
    let text: String
}

enum Result<T>: Equatable where T: Equatable {
    case success(result: T)
    case error
}

此代码将通过问题中指定的所有测试:

func test() {

    // Test 1: Check Post type for equality: OK
    let post1 = Post(text: "post")
    let post2 = Post(text: "post")

    if post1 == post2 {
        print("equal posts")
    }

    // Test 2: Check [Post] type for equality: OK
    let arrayOfPosts1 = [post1, post2]
    let arrayOfPosts2 = [post1, post2]

    if arrayOfPosts1 == arrayOfPosts2 {
        print("equal arrays of post")
    }

    // Test 3: Check Result<Post> type for equality: OK
    let result1 = Result<Post>.success(result: post1)
    let result2 = Result<Post>.success(result: post2)

    if result1 == result2 {
        print("equal results of post")
    }

    // Test 4: Check Result<[Post]> type for equality: OK
    let arrayResult1: Result<[Post]> = Result<[Post]>.success(result: arrayOfPosts1)
    let arrayResult2: Result<[Post]> = Result<[Post]>.success(result: arrayOfPosts2)

    if arrayResult1 == arrayResult2 {
        print("equal results of array of posts")
    }
}

这是输出:

test()
/*
 prints:
 equal posts
 equal arrays of post
 equal results of post
 equal results of array of posts
*/

关于arrays - 为什么数组不符合 Equatable,而它的项在 Swift 中是 Equatable 的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44988705/

相关文章:

arrays - 为什么 $scope 中的数组不使用数组 concat 方法更新?

ios - 我无法弄清楚是什么原因导致消息气泡单元格中出现布局约束警告

swift - 替代 SwiftUI ViewBuilder block 中的 switch 语句?

swift - 当我使用 phpmyadmin 时,它总是告诉我错误,但我不知道它出了什么问题

java - 尝试输入带有空格的字符串时出现 InputMismatchException

python - 我怎样才能找到 numpy 的 Wronskian 行列式

java - 将 JSON 字符串转换为 Java/Python (Jython) 对象?

Java-未找到通用类型?

java - JVM 是否有计划在运行时支持泛型?

generics - 如何使用 Float 特性访问数字常量?