First step would be to describe what you want in a protocol:
protocol Addable {
func add(other : Self) -> Self
}
Then you can make other types conform to it:
extension Int : Addable {
func add(other : Int) -> Int {
return self + other
}
}
Of course this would mean having to write the same code for every type you want to add this add method to. We can do better than this by using a protocol extension to provide the default implementation. But we can't just implement the extension for Addable, the compiler will complain "Binary operator + cannot be applied to two Self operands". This is because this protocol could be implemented by types that don't have a + operator defined. So we need to use a 'where' clause to limit the extension to types that define the + operator. That means we need another protocol, which requires the + operator. Sadly Swift doesn't provide one, so we need to make our own:
protocol DefinesPlusOperator {
func +( lhs : Self, rhs : Self ) -> Self
}
Now we can add this protocol to all our types:
extension Int : DefinesPlusOperator {}
extension Float : DefinesPlusOperator {}
extension CGFloat : DefinesPlusOperator {}
Note that we don't need to provide an implementation here, those types already have the + operator, so we can declare them to conform to this protocol without having to provide an implementation.
With this we can provide a default implementation for all types that conform both to the Addable and DefinesPlusOperator protocols:
extension Addable where Self : DefinesPlusOperator {
func add(other : Self) -> Self {
return self + other
}
}
And again, we must extend our types to conform to this protocol:
extension Int : Addable {}
....
Here we don't have to provide the implementation because we have the default implementation in the protocol extension.
We also can declare types to conform to both protocols at the same time:
extension Double : DefinesPlusOperator, Addable {}
That leaves NSNumber. This is the hardest case here. It doesn't provide the + operator, so we cannot use it with the DefinesPlusOperator default implementation. We would have to create our own implementation:
extension NSNumber : Addable {
func add( other : NSNumber ) -> Self {
return self.dynamicType.init(integer: integerValue + other.integerValue)
}
}
This looks a little bit strange, but it has to be exactly like this because NSNumber is not a final class, so it can be subclassed and the protocol must work for all subclasses as well as the base class. Using self.dynamicType.init to create the result instance ensures that we return the exact same NSNumber subclass as add is called on.
Unfortunately this will crash at runtime because the way NSNumber is implemented as a class cluster. The init(integer:) initializer is not available on all concrete NSNumber subclasses.
We still can add an add method to NSNumber, but we wouldn't be able to make it conform to that Addable protocol. But this is not so easy either, as NSNumber can contain different types of values (booleans, integer, floating point numbers, NSDecimalNumber). So if we just implement it like this we can lose information:
extension NSNumber {
func add(other : NSNumber) -> NSNumber {
return NSNumber(integer: integerValue + other.integerValue)
}
}
My recommendation for dealing with NSNumber would be to immediately convert it to the right Swift type when we receive it and only convert it back if we must pass it to an Objective-C API.