我有一个协议
SomeObjectFactory
,它的方法createSomeObjectWithConfiguration(_ config: SomeObjectConfiguration<T>)
在类Builder中使用。当我尝试用 Swift 5.7 编译这段代码时,我遇到了一个错误
成员“configWithExperience”不能用于“any”类型的值 配置工厂';考虑改用通用约束
下面是实现
import Combine
import Foundation
final class SomeObject<T: Combine.Scheduler> {}
struct Experience {
let id: String
}
struct SomeObjectConfiguration<T: Combine.Scheduler> {
let scheduler: T
}
protocol SomeObjectFactory {
associatedtype T: Combine.Scheduler
func createSomeObjectWithConfiguration(_ config: SomeObjectConfiguration<T>) -> SomeObject<T>
}
protocol ConfigurationFactory {
associatedtype T: Combine.Scheduler
func configWithExperience(_ experience: Experience) -> SomeObjectConfiguration<T>
}
final class Builder<T: Combine.Scheduler> {
private let configurationFactory: any ConfigurationFactory
init(configurationFactory: any ConfigurationFactory) {
self.configurationFactory = configurationFactory
}
func createSomeObject(_ experience: Experience) {
let someObjectConfiguration: SomeObjectConfiguration<T> = configurationFactory.configWithExperience(experience)
}
}
我希望从 Builder 的 configurationFactory 实例创建一个 someObjectConfiguration。
any ConfigurationFactory
确实意味着,anyConfigurationFactory
。无法保证该工厂的 ConfigurationFactory.T
与包含它的 Builder.T
相同。您需要添加这两个应该匹配的约束。
一种方法是使用主要关联类型,如下所示:
// Make `T` a primary associated type
// https://github.com/apple/swift-evolution/blob/main/proposals/0346-light-weight-same-type-syntax.md
+protocol ConfigurationFactory<T> {
-protocol ConfigurationFactory {
associatedtype T: Combine.Scheduler
func configWithExperience(_ experience: Experience) -> SomeObjectConfiguration<T>
}
final class Builder<T: Combine.Scheduler> {
+ // Constant the `T` of the factory to be the `T` of this builder
+ private let configurationFactory: any ConfigurationFactory<T>
- private let configurationFactory: any ConfigurationFactory
// Likewise, update the initializer to match
+ init(configurationFactory: any ConfigurationFactory<T>) {
- init(configurationFactory: any ConfigurationFactory) {
self.configurationFactory = configurationFactory
}
func createSomeObject(_ experience: Experience) {
let someObjectConfiguration: SomeObjectConfiguration<T> = configurationFactory.configWithExperience(experience)
}
}