在Swift中,如何将函数泛化为理解T + T的类型

Jam*_*ack 11 generics swift

我想有一个泛型函数,可以在两个值上使用加号运算符.

class funccalc {
    func doAdd<T>(x:T,y:T) -> T {
        return x + y
    }
}
let a = funccalc()
println(a.doAdd(1, y: 4))
println(a.doAdd(23.54, y:200))
Run Code Online (Sandbox Code Playgroud)

我收到错误 return x + y

我唯一的选择是遵循这个答案中的建议:https://stackoverflow.com/a/24047239/67566,并创建我自己的协议,IntString定义运营商?

mil*_*los 12

您可能对其他函数也有类似的需求,并且为所有整数和浮点类型(或其他"可求"事物)实现它们会导致大量代码重复.

一个部分解决方案,特别是+, - ,*,/,%,是要求符合IntegerArithmeticType协议:

func example<T: IntegerArithmeticType>(x: T, y: T) -> T { return x + y }
println(example(40, 2)) // --> 42
Run Code Online (Sandbox Code Playgroud)

这不适用于浮点类型,因为它们不实现在_IntegerArithmeticType协议中定义的溢出操作,IntegerArithmeticType继承自该操作.

但是,为特定的全局定义的运算符函数一致性扩展类型并不像您想象的那样"烦人":

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

extension Int: Summable {}
extension Double: Summable {}
extension String: Summable {}
// extension for any other types... you are in full control!
Run Code Online (Sandbox Code Playgroud)

你做了一次,然后永远你可以在你的代码中使用Summable:

func example<T: Summable>(x: T, y: T) -> T { return x + y }

println( example("4", "2") ) // --> 42
Run Code Online (Sandbox Code Playgroud)

事实上,正如@connor所指出的,这相当于你提到的@ Jean-PhilippePellet的回答.


Con*_*nor 6

你应该按照建议的答案去做.创建一个供您使用的协议,并扩展您要使用它的所有类.然后确保T在方法签名中实现该协议.

您不能使用"可添加"协议,因为swift中没有一个.swift库实际上为每个有效的加法操作创建了一个函数+.按住Command键点击Int之类的内容,查看所有这些内容的定义.它看起来像这样:

//....
func +(lhs: Int8, rhs: Int8) -> Int8
func +(lhs: UInt16, rhs: UInt16) -> UInt16
func +(lhs: Int16, rhs: Int16) -> Int16
func +(lhs: UInt32, rhs: UInt32) -> UInt32
func +(lhs: Int32, rhs: Int32) -> Int32
//etc...
Run Code Online (Sandbox Code Playgroud)

  • 我希望有另一种方式,因为制作一个新的协议只是为了获得这种类型的功能似乎有点烦人.命令clck操作对我来说是新的,我需要尝试一下. (3认同)

J.b*_*nie 3

您尝试过使用该协议AdditiveArithmetic吗?

https://developer.apple.com/documentation/swift/additivearithmetic

看起来这正是您正在寻找的。该协议具有以下方法:

static func + (Self, Self) -> Self

使用该协议,您的方法将变为:

class funccalc {
    func doAdd<T: AdditiveArithmetic>(x:T,y:T) -> T {
        return x + y
    }
}
Run Code Online (Sandbox Code Playgroud)