当数组的项在Swift中为Equatable时,为什么数组不符合Equatable? [英] Why doesn't array conform to Equatable, when its items are Equatable in Swift?
问题描述
更新:
从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:
- 测试我可以比较两种
Post
类型:确定 - 测试我可以比较两种
[Post]
类型:确定 - 测试我可以比较两种
Result< Post>
类型:确定 - 测试我可以比较两种
Result< [Post]>
类型:错误
- Test that I can compare two
Post
types: OK - Test that I can compare two
[Post]
types: OK - Test that I can compare two
Result<Post>
types: OK - 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屋!