Swift允许您创建一个Array扩展,将Integer与:
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
这个问题不是如何计算数字,而是如何创建一个通用的Array Extension来实现。
越来越近
这是最接近我能够得到的,如果它帮助任何人更接近解决方案:
您可以创建一个可以满足我们所需要做的协议,即:
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,3].sum(0) //6 [1.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,3].sum(0) //6
[1,3].sum() //Could not find member 'sum'
func sum<T where T : Integer,T: Addable>() -> T? { return self.map { $0 as T }.reduce(T()) { $0 + $1 } }
但希望这将有助于其他人更加接近解决方案。
一些进展
从@GabrielePetronella答案看,我们可以调用上述方法,如果我们在调用站点上明确指定类型,如:
let i:Int = [1,3].sum() let d:Double = [1.1,2.2,3.3].sum()
从Swift 2开始,可以使用协议扩展来做到这一点。 (详见
The Swift Programming Language: Protocols)。
首先,Addable协议:
protocol Addable: IntegerLiteralConvertible { func + (lhs: Self,rhs: Self) -> Self } extension Int : Addable {} extension Double: Addable {} // ...
接下来,扩展SequenceType以添加可添加元素的序列:
extension SequenceType where Generator.Element: Addable { var sum: Generator.Element { return reduce(0,combine: +) } }
用法:
let ints = [0,1,3] print(ints.sum) // Prints: "6" let doubles = [0.0,1.0,2.0,3.0] print(doubles.sum) // Prints: "6.0"