swift 引用“PrimitiveSequence”上的示例方法“xxx”要求类型“A”和“any B "等效

1tu0hz3e  于 2023-03-16  发布在  Swift
关注(0)|答案(1)|浏览(86)

我们需要一些建议。我正在尝试做这样的抽象,所以我有很多不同的响应。在项目的某个时候,我们意识到我们的一些响应有id属性,我们想为这些响应做一些通用的逻辑,而不关心这个响应是什么。唯一重要的是这些响应包含id字段。我们引入了WithIdResponse,并创建了包含id的Responses扩展,这些扩展在实现的体系结构上下文中非常有用。
接下来,我们为Single创建了被动虚拟扩展,它可以执行简单的MapWithIdResponse?->String?,我们将此操作符称为id
Swift的问题是,当我们使用id运算符时,编译器会出现以下错误:Referencing instance method 'id()' on 'PrimitiveSequence' requires the types 'ItemAResponse' and 'any WithIdResponse' be equivalent
我们试图理解这个信息,但我们失败了。我们的假设在这里做错了什么吗?

import Foundation
import RxSwift

protocol WithIdResponse {
    var id: String { get }
}

extension PrimitiveSequence where Element == WithIdResponse?, Trait == SingleTrait {
    func id() -> Single<String?> {
        self.map { $0?.id }
    }
}

struct ItemAResponse {
    let id: String
}
extension ItemAResponse: WithIdResponse {}

struct ItemBResponse {
    let id: String
}
extension ItemBResponse: WithIdResponse {}

let subjectA: BehaviorSubject<ItemAResponse?> = BehaviorSubject(value: nil)
let subjectB: BehaviorSubject<ItemBResponse?> = BehaviorSubject(value: nil)

let singleA = subjectA.asSingle().id() // HERE WE HAVE ERROR
fwzugrvs

fwzugrvs1#

您要求Element为Optional<any WithIdResponse>。您需要泛型类型以允许实现任何WithIdResponse
下面是您可以如何做到这一点:

extension PrimitiveSequence where Trait == SingleTrait {
    func id<Wrapped>() -> Single<String?> where Element == Optional<Wrapped>, Wrapped: WithIdResponse {
        self.map { $0?.id }
    }
}

顺便说一句,你知道Swift库中已经有一个Identifiable类型了吗?我建议你使用它,而不是自己制作。
大概是这样的

extension PrimitiveSequence where Trait == SingleTrait {
    func id<Wrapped>() -> Single<Wrapped.ID?> where Element == Optional<Wrapped>, Wrapped: Identifiable {
        self.map { $0?.id }
    }
}

struct ItemAResponse: Identifiable {
    let id: String
}

let subjectA: BehaviorSubject<ItemAResponse?> = BehaviorSubject(value: nil)

let singleA = subjectA.asSingle().id() // This is a `PrimitiveSequence<SingleTrait, String?>`

相关问题