当数组的项在Swift中为Equatable时,为什么数组不符合Equatable? [英] Why doesn't array conform to Equatable, when its items are Equatable in Swift?

查看:248
本文介绍了当数组的项在Swift中为Equatable时,为什么数组不符合Equatable?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:

从Xcode 9.3开始,其中包括 Swift 4.1 ,数组相等性 正常工作,并且原始问题中的代码可以正确编译。

As of Xcode 9.3, which includes Swift 4.1, the array equality works as expected, and the code in the original question compiles without errors.

但是,请参阅已接受的答案,因为

原始问题如下:

当我尝试声明类型为 [Post] 的通用枚举的实例时,出现错误提示

When I try to declare an instance of a generic enum with type [Post], I get an error saying


类型'[Post]'不符合协议'Equatable'

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

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

which is nonsense, because Post conforms to Equatable and I can actually compare two [Post] instances with no compilation errors?

在以下示例中,我扩展了 Post Result< T> 类型,且类型为 Equatable zh_cn我做了一些测试:

In the following example, I extend Post and Result<T> types with Equatable and then I do a few tests:


  1. 测试我可以比较两种 Post 类型:确定

  2. 测试我可以比较两种 [Post] 类型:确定

  3. 测试我可以比较两种 Result< Post> 类型:确定

  4. 测试我可以比较两种 Result< [Post]> 类型:错误

  1. Test that I can compare two Post types: OK
  2. Test that I can compare two [Post] types: OK
  3. Test that I can compare two Result<Post> types: OK
  4. Test that I can compare two Result<[Post]> types: ERROR



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 现在符合平等,因此无需使用任何替代方法即可解决此问题。

With the introduction of conditional conformance in Swift 4.1, Array now conforms to Equatable, so the issue should be resolved without the need to resort to any workarounds.

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

Also, Swift now allows a type to automatically synthesize Equatable conformance, provided all its members are Equatable, simply by declaring Equatable conformance as part of the original type definition (not an extension) but without implementing any of its requirements. This works for enums provided associated values, if any, are Equatable.

现在可以更简洁地编写此问题的代码,如下所示:

The code from this question can now be written much more concisely as below:

import Foundation

struct Post: Equatable {
    let text: String
}

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

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

This code will pass all the tests specified in the question:

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
*/

这篇关于当数组的项在Swift中为Equatable时,为什么数组不符合Equatable?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆