对于子类来说,遵守通用约束似乎是不可能的

问题描述 投票:0回答:1

我已将代码缩减为以下最简单的版本来显示问题。我不知道为什么 Swift 会抱怨。

为什么

DatabaseGateway
需要遵守协议
Something
???

struct Database {}

open class DatabaseGateway {
    
    let database: Database
    
    public init() {
        database = Database()
    }
}

struct FilterParameter<T> {}

protocol Something {
    associatedtype T: RawRepresentable where T.RawValue == String
    var filterParameter: FilterParameter<T> { get }
}

enum VoteTable {}

extension VoteTable {
    
    enum Field: String {
        case value = "value"
    }
}

final class User: DatabaseGateway, Something {
    let filterParameter = FilterParameter<VoteTable.Field>()
}

final class Poll: DatabaseGateway, Something {
    let filterParameter = FilterParameter<VoteTable.Field>()
}

struct VoteRecordFilter {
    
    let parameters: [Parameter]
    
    init(parameter: Parameter) {
        self.init(parameters: [parameter])
    }
    
    init(parameters: [Parameter]) {
        self.parameters = parameters
    }
    
    init<S: Something>(parameters: [S]) where S.T == VoteTable.Field {
        self.init(parameters: parameters.map({
            $0.filterParameter
        }))
    }
        
    typealias Parameter = FilterParameter<VoteTable.Field>
}

extension Poll {
    
    func voteSubmitted(user: User) async throws -> Bool {
        let filter = VoteRecordFilter(parameters: [self, user]) // Initializer 'init(parameters:)' requires that 'DatabaseGateway' conform to 'Something'
        return true
    }
}
swift generics
1个回答
0
投票

您要调用的初始化程序采用类型参数

S
。在通话中
S
应该是什么?

VoteRecordFilter(parameters: [self, user])

既不是

[self, user]
也不是
[Poll]
。 Swift 推断表达式的类型为
[User]
,并尝试使用
[DatabaseGateway]
来表示
DatabaseGateway
S
DatabaseGateway
不符,因此出现错误。事实上,没有类型
Something
允许将
S
传递给
[self, user]
您可以采用一组存在类型,而不是使其通用,

parameters:

您还应该添加 
init(parameters: [any Something<VoteTable.Field>]) { self.init(parameters: parameters.map(\.filterParameter)) }

作为

T
的主要关联类型,以便
Something
正常工作。
Something<VoteTable.Field>

	
© www.soinside.com 2019 - 2024. All rights reserved.