Extension of constructed generic type in Swift

前端 未结 7 731
闹比i
闹比i 2020-12-02 13:56

Is it possible to extend an generic class for a specialised/constructed generic type? I would like to extend Int Arrays with a method to calculate the sum of its elements.

7条回答
  •  [愿得一人]
    2020-12-02 14:42

    Looks like you can't. The closest we can get is the function

    func sum(a:Array) -> Int {
        return a.reduce(0) {$0 + $1}
    }
    

    Swift will allow you to add extension on the Array class but not specifically to a specialized version of the class.

    error: :108:1: error: non-nominal type 'Array' cannot be extended

    You can extend the Array class.

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

    The problem is now with the + operator

    error: :102:16: error: could not find an overload for '+' that accepts the supplied arguments
            return reduce(0) { $0 + $1 }
    

    This is somewhat expected since we cannot be sure that the + operator will be will be overloaded for all the possible types that could be used in an array.

    So we could try to constraint the operation only on certain classes. Something like

    class Dummy {
    }
    
    extension Array {
        func someFunc() -> Int {
           return 0
        }
    }
    
    var l = [Dummy()]
    var r = l.someFunc() // Expect 0
    

    Conceptually this should work (currently it seems that there is a bug, Xcode crashes when evaluating a playground using this code). In the eventually that it works, we cannot use this trick since the type Int is not a class.

    extension Array {
        func sum() -> T {
            return reduce(0) { $0 + $1 }
        }
    }
    
    error: :101:14: error: inheritance from non-protocol, non-class type 'Int'
        func sum() -> T {
    

    I also looked at extending the Array class with a protocol but again Int not being a class makes it impossible. If the numeric types were classes, it would be nice if we could have a protocol to define that a class can be added just like Comparable or Equatable but my understanding is that protocol cannot define generic function which would be needed to create a Addable protocol.

    Edit:

    As stated by other answers, you can make it work for Int by explicitly checking and casting to Int in the closure. I guess I missed it will investigating. But it would still be nice if we could have a generic way of working with numeric types.

提交回复
热议问题