你如何编写一个协议来指定Swift中算术运算符的存在?

时间:2018-03-13 00:06:17

标签: swift generics protocols

这是一个例子。编写一个函数来乘以两个双精度非常简单:

func MultiplyDoubles(_ x: Double, _ y: Double) {
    return x * y
}
MultiplyDoubles(3,5) // returns 15

但是假设我想编写一个通用函数来执行此操作:

func MultiplyValues<T>(_ x: T, _ y: T) {
    return x * y //ERROR
}
MultiplyValues(3, 5)

但这会引发错误:Binary operator '*' cannot be applied to to 'T' operands

我知道我需要编写一个协议,指明*可以应用于它,但我该如何做?

我尝试过:

protocol Multipliable {
    static func *(A:Multipliable, B: Multipliable) -> Multipliable
}
func MultiplyValues<T: Multipliable>(_ x: T, _ y: T) -> Multipliable {
    return x * y
}
MultiplyValues(3, 5)

虽然这会返回消息

error: MyPlayground.playground:15:19: error: argument type 'Int' does not conform to expected type 'Multipliable'
MultiplyValues(3, 5)
                  ^

研究: 我已经查看了protocols的文档以及genericsoperators的文档。我不是在写一个通用的协议,而是一个正常的协议,它指的是它可以成倍增加。本文档解释了如何重载运算符,以及如何创建泛型函数,以及如何使用具有泛型函数的协议,但它们都没有解释如何编写指定运算符可以应用于协议的协议。

2 个答案:

答案 0 :(得分:4)

您可以使用现有的Numeric协议:

func multiply<T: Numeric>(_ x: T, _ y: T) -> T {
    return x * y
}

但是,让我们假设这样的协议不存在。您可以定义自己的,并指定哪些类型符合此协议:

protocol Multipliable {
    static func *(lhs: Self, rhs: Self) -> Self
}

// These types already implement the above method, so all you need to do
// is declare conformance to your protocol with an empty extension.

extension Int: Multipliable { }
extension Double: Multipliable { }

// repeat for other types as you see fit

然后你可以这样做:

func multiply<T: Multipliable>(_ x: T, _ y: T) -> T {
    return x * y
}

答案 1 :(得分:1)

你可以写这样的东西。

protocol Multipliable {
    static func *(A:Self, B: Self) -> Self
}
extension Int : Multipliable {}
//You need other extensions for other numeric types...

func MultiplyValues<T: Multipliable>(_ x: T, _ y: T) -> T {
    return x * y
}

MultiplyValues(3, 5)

但是目前的Swift有一些数字协议,你应该更好地利用它们(如Rob的回答)。