Swift中构造泛型类型的扩展

Ale*_*sti 48 generics swift

是否可以为专用/构造的泛型类型扩展泛型类?我想用一种方法扩展Int Arrays以计算其元素的总和.

例如

extension Array<Int> {

    func sum() -> Int {
        return reduce(0) { $0 + $1 }
    }

}
Run Code Online (Sandbox Code Playgroud)

ABa*_*ith 48

这可以使用协议扩展来实现(有关更多信息,请参阅Swift编程语言:协议).在Swift 3中:

总而言之,Int你可以这样做:

extension Sequence where Iterator.Element == Int {
    var sum: Int {
        return reduce(0, +)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

let nums = [1, 2, 3, 4]
print(nums.sum) // Prints: "10"
Run Code Online (Sandbox Code Playgroud)

或者,对于更通用的内容,您可以使用@Wes Campaigne建议并创建Addable协议:

protocol Addable {
    init()
    func + (lhs: Self, rhs: Self) -> Self
}

extension Int   : Addable {}
extension Double: Addable {}
extension String: Addable {}
...
Run Code Online (Sandbox Code Playgroud)

接下来,扩展Sequence以添加Addable元素序列:

extension Sequence where Iterator.Element: Addable {
    var sum: Iterator.Element {
        return reduce(Iterator.Element(), +)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

let doubles = [1.0, 2.0, 3.0, 4.0]
print(doubles.sum) // Prints: "10.0"

let strings = ["a", "b", "c"]
print(strings.sum) // Prints: "abc"
Run Code Online (Sandbox Code Playgroud)

  • @GitSyncApp,谢谢你让我知道!完成. (2认同)

Wes*_*gne 8

管理以便以可扩展的通用方式工作而不会过度滥用类型系统,但它有一些限制.

protocol Addable {
    func +(lhs: Self, rhs: Self) -> Self
    class var identity: Self { get }
}

extension Int : Addable {
    static var identity: Int { get { return 0 } }
}

extension String : Addable {
    static var identity: String { get { return "" } }
}

extension Array {
    func sum<U : Addable>() -> U? {
        let s: U? = U.identity
        return self.sum(s)
    }

    func sum<U : Addable>(start: U?) -> U? {
        return reduce(start) { lhs, rhs in
            switch (lhs, rhs) {
            case (.Some(let left), let right as U):
                return left + right
            default:
                return nil
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

具体来说:使用此解决方案,类型推断将无法在无参数sum()方法上工作,因此您必须注释预期的返回类型或为其指定一个起始值(从中可以推断出类型).

另请注意,这将返回Optional类型的值:如果由于任何原因无法从数组计算预期类型的​​总和,则返回nil.

为了显示:

let int_array = Array(1...10)

let x: Int? = int_array.sum() // result: {Some 55}
let x2 = int_array.sum(0) // result: {Some 55}
let x3 = int_array.sum() // Compiler error because it can't infer type


let string_array = ["a", "b", "c"]

let y: String? = string_array.sum() // result: {Some "abc"}
let y2 = string_array.sum("") // result: {Some "abc"}

let y3: Int? = string_array.sum() // result: nil  (can't cast String to Int)
let y4 = string_array.sum(0) // result: nil  (can't cast String to Int)


let double_array = [1.3, 4.2, 2.1]

let z = double_array.sum(0.0) // Compiler error because we haven't extended Double to be Addable
Run Code Online (Sandbox Code Playgroud)


小智 6

斯威夫特 5.x:

extension Array where Element == Int {

    var sum: Int {
        reduce(0, +)
    }
}
Run Code Online (Sandbox Code Playgroud)