【问题标题】:Type 'any SomeProtocol' cannot conform to 'SomeOtherProtocol'键入 \'any SomeProtocol\' 不能符合 \'SomeOtherProtocol\'
【发布时间】:2022-11-27 12:08:20
【问题描述】:

我想使用这样的东西,但我不明白为什么它不起作用:

protocol InitProtocol {
    init()
}

protocol SomeServiceProtocol: InitProtocol {}

class SomeManager {
    func initService<T: InitProtocol>(type: T.Type) -> T {
        type.init()
    }
}

class SomeViewModel {
    let someService: SomeServiceProtocol

    init(someService: SomeServiceProtocol = SomeManager().initService(type: SomeServiceProtocol.self)) {
        self.someService = someService
    }
}

SomeViewModel 初始化中的依赖项注入抛出一个错误:"Type 'any SomeServiceProtocol' cannot conform to 'InitProtocol'"

SomeServiceProtocol清楚符合InitProtocol,所以我假设编译器真正在说的是因为类型T在通用函数initService()中被声明为符合InitProtocol,任何试图使用返回对象的东西都只会识别它作为 InitProtocol 的一个实例,而不是传入的内容。有没有办法解决这个问题?

笔记

下面的代码编译得很好,但它不允许我初始化T

class SomeManager {
    func initService<T>(type: T.Type) -> T? {
        nil
    }
}

class SomeViewModel {
    let someService: SomeServiceProtocol
   
    init(someService: SomeServiceProtocol = SomeManager().initService(type: SomeServiceProtocol.self)!) {
        self.someService = someService
    }
}

【问题讨论】:

  • 需要明确的是,一个协议不能符合另一个协议,但它可以扩展它(继承自)所以 SomeServiceProtocol 扩展了 InitProtocol。
  • 您需要将真实类型传递给 initService 调用而不是协议
  • initService 以具体类型作为参数,协议不是具体类型,协议是存在类型。在尝试随机示例之前了解协议和泛型可能会有所帮助
  • @JoakimDanielson 感谢您的回答。我在底部添加了一个注释来概述什么是有效的。您知道是否有一种方法可以实现在 func 中初始化泛型类型并返回它?
  • 你可以用class SomeViewModel&lt;M : SomeServiceProtocol&gt; { let someService: MSomeManager().initService(type: M.self)来做,但是你不能通过一个协议。在 Swift 5.7 中,有一个新的语法 some SomeServiceProtocol,它实际上与受协议约束的泛型相同。

标签: swift generics protocols swift-protocols


【解决方案1】:

假设您有一个具体的 SomeServiceProtocol 类,例如。 :

final class AnyService: SomeServiceProtocol {
    init() { }
}

你可以这样写你的经理:

class SomeManager {
    func initService() -> any InitProtocol {
        AnyService()
    }
}

并在您的视图模型中使用它:

class SomeViewModel {
    let someService: any InitProtocol

    init(someService: any InitProtocol = SomeManager().initService()) {
        self.someService = someService
    }
}

您还可以将它与其他一些服务一起使用:

final class SomeOtherService: SomeServiceProtocol {
    init() { }
}

let some = SomeViewModel(someService: SomeOtherService())
print(some.someService)

这对你有用吗?

【讨论】:

    猜你喜欢
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 2022-10-31
    • 1970-01-01
    相关资源
    最近更新 更多