如何约束Swift泛型类型参数为任何协议和另一个参数,以符合它?



我正在尝试为依赖注入创建一个属性包装器:

@propertyWrapper struct Dependency<T> {
private(set) var wrappedValue: T
init() {
wrappedValue = Dependencies.shared.resolve()
}
}
final class Dependencies {
static let shared = Dependencies()
private var dependencies = [String: AnyObject]()
func register<T, P>(_ dependency: T, as: P.Type) {
let key = String(describing: P.self)
dependencies[key] = dependency as AnyObject
}
func resolve<T>() -> T {
let key = String(describing: T.self)
let dependency = dependencies[key] as? T
precondition(dependency != nil, "No dependency found for (key)! must register a dependency before resolve.")
return dependency!
}
}

目的是注册一个符合协议的对象,然后根据协议类型查找。

例如:

protocol Foo {
func foo() -> String
}
class Bar: Foo {
func foo() -> String {
"Hello World!"
}
}
Dependencies.shared.register(Bar(), as: Foo.self)
struct Test {
@Dependency var a: Foo
}
let t = Test()
print(t.a.foo())

正常工作-打印"Hello World!">

但是,我也可以这样做:

Dependencies.shared.register("not a Bar", as: Foo.self)

和前提条件爆发,因为String不符合Foo。

我要做的是约束func register<T, P>(_ dependency: T, as: P.Type)使T必须符合p

register<T: P, P>(_ dependency: T, as: P.Type)这样的东西-显然不起作用。

这可能吗?

我认为这个改变一定符合你的期望:

func register<T>(_ dependency: T, as dependencyType: T.Type) {
let key = String(describing: dependencyType)
dependencies[key] = dependency as AnyObject
}

(其余代码保持不变)

那么这行困扰你不编译(Cannot convert value of type 'String' to expected argument type 'Bar'):

Dependencies.shared.register("not a Bar", as: Bar.self)

相关内容