使用ReactiveSwift map函数在Swift中实现协议约束Equatable

bakd9h0s  于 2023-05-05  发布在  Swift
关注(0)|答案(1)|浏览(179)

我使用ReactiveSwift。有两种协议:CommonProtocolSpecificProtocol。当我在map函数中使用SpecificProtocol时,出现错误Type 'any SpecificProtocol' cannot conform to 'Equatable'。但是,使用ConreateItem完全没有问题

protocol CommonProtocol {}

protocol SpecificProtocol: CommonProtocol, Equatable

extension SpecificProtocol where Self: Equatable {
    static func == (lhs: Self, rhs: Self) -> Bool { return true }
}

class ConreateItem: SpecificProtocol{}

var messages = MutableProperty<[CommonProtocol]?>(nil)

messages.producer
//  .map({ $0 as? [ConreateItem] }) //that is ok
    .map({ $0 as? [any SpecificProtocol] })//Type 'any SpecificProtocol' cannot conform to'Equatable'
    .skipRepeats()

我不明白为什么/如何将SpecificProtocol转换为any SpecificProtocol。什么是正确的方式来实现协议上的Equatable约束,以便我可以在map函数中使用它(在我的情况下,高阶函数需要EquatablemapReactiveSwift

bihw5rsg

bihw5rsg1#

Equatable中的tl;dr ==要求两个参数具有相同的具体类型。如果编译器只知道两个示例中的每一个都是any Equatable,则无法确定这一点。
如果不仔细研究skipNil(),看起来它需要一个符合Equatable的对象序列。SpecificProtocol没有声明与Equatable的一致性,它只是声明了一个函数==(它有一个编译器错误,因为它没有返回Bool),所以有一个类型错误。
顺便说一下,注意protocols在Swift中不是类型,这就是为什么“any”在那里。它是“任何类型符合SpecificProtocol的东西”的缩写。在将来的某个时候,您将不得不在声明中显式地写入any。例如[any SpecificProtocol]
要使SpecificProtocol示例符合Equatable,您需要

protocol SpecificProtocol: CommonProtocol, Equatable
{
...
}

您可以保留扩展来定义默认的==函数,也可以允许具体类型定义自己的函数实现。

更新

即使SpecificProtocol符合Equatable,您也会看到错误消息的原因是,不能比较都符合Equatable的任意类型的示例是否相等。不允许"foo" == 3,即使StringInt都是相等的。
为了使从map返回的数组是Equatable,它必须能够将它的元素与另一个相同类型的数组的元素进行比较,如果你对这些元素一无所知,除了它们都符合SpecificProtocol之外,你不能比较它们的相等性,因为Equatable一致性要求==的两个参数都是相同的 * 具体 *类型。
另外,我认为map闭包不应该返回数组。我觉得应该是.map({ $0 as? any SpecificProtocol })

相关问题