Swift 泛型 - 协议(protocol)不符合协议(protocol)

标签 swift generics swift4

我正在尝试获取一个容器,该容器实现一组协议(protocol),我将这些协议(protocol)作为参数传递给原始容器上的函数。

struct Container {
  let someProperty: String
  let otherProperty: String
}

// Subcontainers
protocol Base {}
protocol SomePropertyContainer: Base {
  var someProperty: String { get }
}

protocol OtherPropertyContainer: Base {
  var otherProperty: String { get }
}

extension Container: SomePropertyContainer, OtherPropertyContainer {}


// Sub Container Provisioning Protocol
protocol SubContainerProviderProtocol {
  func subContainer<T: Base>(protos: T.Type) -> T?
}

extension Container: SubContainerProviderProtocol {

  func subContainer <T: Base>(protos: T.Type) -> T? {
    return self as? T
  }
}

// Example container
let subContainerProvider: SubContainerProviderProtocol = Container(someProperty: "Why does this not work!", otherProperty: "Seriously.")

启动并运行它可以让我将 ContainerProviderProtocol 注入(inject)消费者,同时让他们有可能自行指定他们真正想要的 SubContainer

例如只对 someProperty 感兴趣的类可能如下所示

// Example Container Provider consumer
class SomeClass {

  let subContainerProvider: SubContainerProviderProtocol

  init(subContainerProvider: SubContainerProviderProtocol) {
    self.subContainerProvider = subContainerProvider
  }

  func printSomeProperty() {
    let someProperty = subContainerProvider
      .subContainer(protos: SomePropertyContainer.self)?
      .someProperty
    print(someProperty)
  }
}

// Example call
let someClass = SomeClass(subContainerProvider: subContainerProvider)
someClass.printSomeProperty() // "Why does this not work!"

这个解决方案对于依赖注入(inject)和可测试性来说是不可思议的。

但是限制 T: Base 导致了编译器错误

In argument type 'SomePropertyContainer.Protocol', 'SomePropertyContainer' does not conform to expected type 'Base'

不指定符合 Base 将编译,但也允许将任何类型作为 T 传递。

我已经尝试在附加协议(protocol)等中使用关联类型,但还没有弄明白。虽然这个问题非常有趣,但我的想法已经用完了。

可能与(但不完全相同)https://bugs.swift.org/browse/SR-55 有关

最佳答案

这就是问题所在:在某些时候,您必须开始使用实际类型,而不仅仅是协议(protocol)。你的线路:

func container<T: Base>(protos: T.Type) -> T?

告诉编译器你要给这个函数一个类型,通常是 T,它符合协议(protocol) Base,而不是另一个协议(protocol)。你需要这样的东西:

class SPC: SomePropertyContainer {
    var someProperty: String = ""
}

class SomeClass {
    let containerProvider: ContainerProviderProtocol
    init(containerProvider: ContainerProviderProtocol) {
        self.containerProvider = containerProvider
    }

    func printSomeProperty() {
        let someProperty = containerProvider
            .container(protos: SPC.self)?
            .someProperty
        print(someProperty)
    }
}

SPC 是一种符合 SomePropertyContainer 协议(protocol)的类型,它本身也符合 Base 协议(protocol),所以这就是您的代码所期望的。

关于Swift 泛型 - 协议(protocol)不符合协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51178395/

相关文章:

swift - 错误 : generic parameter 'Key' could not be inferred when creating a Dictionary

ios - Swift 4数据读取选项

ios - 如何在 swift 4 的 didSelectItemAt IndexPath 中的数组中嵌入字典类型数据?

ios - 根据 URL 更改 UIImageView

ios - 在 UIViewController 中关闭键盘

android - 是否有与 iOS 的(swifts)fatalError() 等效的 Android?

c# - 将 T 限制为字符串和整数?

java - 引用与泛型不明确

c# - 使用 System.Type 中的泛型类型调用泛型方法

ios - Firebase 加入多个节点对象