Swift可让您创建一个将Integer与之相加的Array扩展:
extension Array {
func sum() -> Int {
return self.map { $0 as Int }.reduce(0) { $0 + $1 }
}
}
现在可以用来总结Int[]
如下:
[1,2,3].sum() //6
但是我们如何制作一个通用的版本,该版本也支持对其他Number类型进行求和Double[]
?
[1.1,2.1,3.1].sum() //fails
这个问题不是如何对数字求和,而是如何创建通用数组扩展来实现。
如果可以帮助任何人更接近解决方案,这是我能够获得的最接近的结果:
您可以创建一个可以满足我们需要做的协议,即:
protocol Addable {
func +(lhs: Self, rhs: Self) -> Self
init()
}
然后扩展我们想要支持的符合上述协议的每种类型:
extension Int : Addable {
}
extension Double : Addable {
}
然后添加具有该约束的扩展:
extension Array {
func sum<T : Addable>(min:T) -> T
{
return self.map { $0 as T }.reduce(min) { $0 + $1 }
}
}
现在可以将其用于我们为支持该协议而扩展的数字,即:
[1,2,3].sum(0) //6
[1.1,2.1,3.1].sum(0.0) //6.3
不幸的是,我不得不提供一个参数就无法使它工作,即:
func sum<T : Addable>(x:T...) -> T?
{
return self.map { $0 as T }.reduce(T()) { $0 + $1 }
}
修改后的方法仍然可以使用1个参数:
[1,2,3].sum(0) //6
但是在不带参数调用时无法解析该方法,即:
[1,2,3].sum() //Could not find member 'sum'
添加Integer
到方法签名也无助于方法解析:
func sum<T where T : Integer, T: Addable>() -> T?
{
return self.map { $0 as T }.reduce(T()) { $0 + $1 }
}
但是希望这将帮助其他人更接近解决方案。
从@GabrielePetronella答案来看,如果我们在调用站点上明确指定类型,则可以调用上述方法:
let i:Int = [1,2,3].sum()
let d:Double = [1.1,2.2,3.3].sum()
从Swift 2开始,可以使用协议扩展来做到这一点。(有关更多信息,请参见Swift编程语言:协议)。
首先,该Addable
协议:
protocol Addable: IntegerLiteralConvertible {
func + (lhs: Self, rhs: Self) -> Self
}
extension Int : Addable {}
extension Double: Addable {}
// ...
接下来,扩展SequenceType
以添加Addable
元素序列:
extension SequenceType where Generator.Element: Addable {
var sum: Generator.Element {
return reduce(0, combine: +)
}
}
用法:
let ints = [0, 1, 2, 3]
print(ints.sum) // Prints: "6"
let doubles = [0.0, 1.0, 2.0, 3.0]
print(doubles.sum) // Prints: "6.0"
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句