Swift泛型-协议不符合协议

Swift泛型-协议不符合协议,swift,generics,swift4,Swift,Generics,Swift4,我试图得到一个容器,它实现了一组协议,我将这些协议作为参数传递给原始容器上的函数 struct Container { let someProperty: String let otherProperty: String } // Subcontainers protocol Base {} protocol SomePropertyContainer: Base { var someProperty: String { get } } protocol OtherPropert

我试图得到一个容器,它实现了一组协议,我将这些协议作为参数传递给原始容器上的函数

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.")
这个解决方案对于依赖注入和可测试性来说是难以置信的

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

在参数类型“SomePropertyContainer.Protocol”中,“SomePropertyContainer”不符合预期的类型“Base”

不指定与Base的一致性将编译,但也允许将任何类型作为T传递

我已经尝试过在附加协议中使用相关类型等,但是还没有找到答案。虽然这个问题非常有趣,但我已经没有什么想法了


可能与(但不完全相同)

问题是:在某个时候,您必须开始使用实际类型,而不仅仅是协议。您的线路:

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

SPC是一种符合SomePropertyContainer协议的类型,而SomePropertyContainer协议本身也符合基本协议,因此这就是您的代码所期望的。

谢谢。这正是我的代码所期望的,但是我怎样才能让他期望一个协议而不是一个类类型呢?我认为你不能。在某个时刻,您必须实际传入一个类型——对象或结构。最终,泛型代码必须以特定的方式使用。
func container<T: Base>(protos: T.Type) -> T?
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)
    }
}