我们正在尝试创建一个addQueryItem
最终在内部使用字符串和可选字符串的函数。
为了在 API 中获得更大的灵活性,而不是String
用于参数类型,我们改为使用CustomStringConvertible
(String 实现的),因此我们可以使用任何可以表示为字符串的东西。
此外,因此我们可以传递String
基于 it 的枚举,我们还希望它接受自身为 a 的RawRepresentable
类型。RawValue
CustomStringConvertible
然而,由于我们现在在技术上接受每个参数的两种不同类型的值,我们最终不得不为这两种类型的每种组合创建一个“重载矩阵”——总共四个。
我的第一个想法是通过扩展来使用面向协议的编程,RawRepresentable
因此CustomStringConvertible
如果它RawValue
也是一个CustomStringConvertible
. 然后我可以直接将它传递给接受两个CustomStringConvertible
参数并消除其他三个参数的版本。但是,编译器不喜欢它,因为我正在尝试扩展协议,而不是具体类型。
// This doesn't work
extension RawRepresentable : CustomStringConvertible
where RawValue:CustomStringConvertible {
var description: String {
return self.rawValue
}
}
由于无法执行上述操作,如前所述,我必须具备以下所有四个:
func addQueryItem(name:CustomStringConvertible, value:CustomStringConvertible?){
if let valueAsString = value.flatMap({ String(describing:$0) }) {
queryItems.append(name: String(describing:name), value: valueAsString)
}
}
func addQueryItem<TName:RawRepresentable>(name:TName, value:CustomStringConvertible?)
where TName.RawValue:CustomStringConvertible {
addQueryItem(name: name.rawValue, value: value)
}
func addQueryItem<TValue:RawRepresentable>(name:CustomStringConvertible, value:TValue?)
where TValue.RawValue:CustomStringConvertible {
addQueryItem(name: name, value: value?.rawValue)
}
func addQueryItem<TName:RawRepresentable, TValue:RawRepresentable>(name:TName, value:TValue?)
where TName.RawValue:CustomStringConvertible,
TValue.RawValue:CustomStringConvertible
{
addQueryItem(name: name.rawValue, value: value?.rawValue)
}
那么,既然看起来不可能RawRepresentable
坚持CustomStringConvertible
,还有其他方法可以解决这个“重载矩阵”问题吗?