我需要使用不仅符合协议的对象,还要公开它们符合的 second 协议的类型。 (这适用于NSXPCConnection,您不仅可以配置代理对象,还可以告诉它应该在该代理对象上公开哪个协议。)
我尝试过类似的事情:
protocol Conformer where Self : Conformer.P {
associatedtype P : Protocol
static var interface : P {get}
init(info: String)
}
func exposeOverXPC<T:Conformer>(_ _: T.Type) {
let c : NSXPCConnection = …
c.exportedInterface = NSXPCInterface(with: T.interface)
c.exportedObject = T(info:"foo")
}
但它会导致错误:
关联类型'P'只能与具体类型或通用参数库一起使用
具体来说,我希望exposeOverXPC
只接受以下对象:
interface
interface
这是我陷入困境的最后一步,有什么方法可以实现它吗?
答案 0 :(得分:3)
你不能限制谁符合协议,如果你考虑的话,这首先违背了拥有协议的概念。但是,您可以在exposeOverXPC
。
protocol Interface {
}
protocol XPCExposable {
associatedtype P: Interface
init(info: String)
static var interface: P { get }
}
func exposeOverXPC<T: XPCExposable & Interface>(_ : T.Type) {
// 1: T is initializeable in a particular way
// 2: Has a static property interface which references a protocol
// 3: Are themselves conformant to said interface
}
是的,此约束T
符合Interface
而非P
,您最好的选择是exposeOverXPC
私有/内部并提供API
s期望Interface
子类型。只要您有权访问Interface
子类型,就会公开该API。例如:
解决方案1
protocol InterfaceSubType: Interface {
fun test()
}
/// Create as many `API`s as the number of `Interface` subtypes you have.
func exposeOverXPC<T: XPCExposable & InterfaceSubType>(_ : T.Type) {
exposeOverXPC(T.self)
}
/// set to private, you only want to expose the APIs with `Interface` subtype.
private func exposeOverXPC<T: XPCExposable & Interface>(_ : T.Type) {
// Impl.
}
解决方案2
使用具有类型为关联类型的参数的函数的替代解决方案是通过扩展协议来添加该api(如果您愿意,可以作为静态函数)。您必须知道此扩展程序中Interface
的所有预期子类型。
extension XPCExposable {
static func exposeOverXPC<T>(_ interface: P, _ xpcType: T.Type) where T: XPCExposable {
// Expected subtype Interface
if let subInterface = interface as? InterfaceSubType {
subInterface.test()
}
// Other subtypes here.
}
}
可以被称为:
let impl = Impl(info: "")
Impl.exposeOverXPC(Impl.interface, Impl.self)
它是XPCExposable
的扩展程序,因此您将调用者限制为conformer,参数需要XPCExposable.P
,因此您已全部设置。
该解决方案的缺点是:
if
条件,我不知道那些值得一提的是除了我想推出第一个解决方案之外的其他方面。