【发布时间】:2021-02-09 20:20:25
【问题描述】:
在通用处理链中,我有一个处理结果的方法。如果泛型 Type 恰好符合协议,我想进行不同的处理。
我想重载基于协议一致性的方法。这种切换方法可以通过编译器(如果基于协议一致性的切换没有)。
不幸的是,当从处理链中尚未为该协议键入的方法调用编译器时,编译器从不使用更具体的重载。这目前不可能吗?
这是一个例子:
protocol MyProtocol {
var protocolString: String { get }
}
struct SpecialResult: MyProtocol {
let protocolString: String = "special MyProtocol"
}
func preProcess<T>(result: T) {
// Process chain for any kind of T
print("PreProcess: T conforms to MyProtocol: \(T.self is MyProtocol.Type)") // always prints true
process(result: result)
}
func process<T>(result: T) where T: MyProtocol { // Doesn't matter if I use process<T: MyProtocol>
// process specifically for MyProtocol
print("I'm processing a \(result.protocolString) result!")
}
func process<T>(result: T) {
// process generically for T
print("I'm processing a result.")
print("Process: T conforms to MyProtocol: \(T.self is MyProtocol.Type)") // always prints true
}
let result = SpecialResult()
preProcess(result: result)
process(result: result)
// PreProcess: T conforms to MyProtocol: true
// I'm processing a result.
// Process: T conforms to MyProtocol: true
// I'm processing a special MyProtocol result!
我希望它会打印两次特殊的 MyProtocol 行。
对此有任何解决方案吗?即使没有方法重载,我似乎也无法让路由工作。
我可以跳过重载并使用两个不同的方法名,在 if T.self is MyProtocol.Type 后面调用每个方法名,但编译器仍然抱怨真实情况需要符合 MyProtocol,如果是真实情况,它显然必须遵守!
我可以转换result as? MyProtocol,但随后我失去了它的底层类型,这是我在整个处理链中都需要的。我真的需要一种方法来做类似result as? T: MyProtocol 之类的事情,但我似乎找不到如何...
【问题讨论】:
-
我认为您正在想象一个不存在的层次结构或重载的使用。
-
你是什么意思?在泛型链之外,重载路由到正确的方法。在
preProcess之外,result显然可以是任何类型,并且可以正常工作。在preProcess内部,result也可以是任何类型,但它不起作用。 -
不,它没有在通用链之外进行任何动态路由。这一切都发生在编译时。你说
let result = SpecialResult()所以编译器知道这是什么东西。因此,当您说process时,您会得到 MyProtocol 的那个。不过,总的来说,使用where子句进行某种重载和调度的想法是一个错误的目标。这不是 Swift 的工作方式。问题中“过载”一词的使用说明了问题。 -
我看不出这有什么根本不同,编译器在将
result传递给process<T>(result: T)时知道它的类型,但在你将它传递给preProcess<T>(result: T) { process<T>(result: T) }时却不知道。我的意思是它适用于类型,但不是协议类型。我知道它目前没有这样做。但这似乎不是因为您陈述的原因(当不将协议与您的泛型一起使用时效果很好)。 -
@matt 至于重载是错误的方法。这是我尝试处理泛型类型 T 的第 10 种方法,如果 T: MyProtocol 稍有不同,不会将对象折叠成一个 MyProtocol,并失去其固有的 T 特性。
标签: swift generics methods overloading protocols