【问题标题】:How do you write a protocol specifying the existence of an arithmetic operator in Swift?你如何编写一个协议来指定 Swift 中算术运算符的存在?
【发布时间】:2018-03-13 00:06:16
【问题描述】:

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

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 的文档。我不是在写一个通用协议,而是一个普通协议,旨在指定它可以成倍增加。该文档解释了如何重载运算符,以及如何创建泛型函数,以及如何使用具有泛型函数的协议,但没有一个解释如何编写一个协议来指定一个运算符可以应用于协议。

【问题讨论】:

  • 编辑您的问题并讨论您在 google 搜索通用协议时发现了什么,以及为什么它对您没有帮助。
  • Rob 的回答恰到好处 IMO,但在你走得太远之前,请务必阅读 oleb.net/blog/2016/12/protocols-have-semantics。 “* 可以应用于它”与“可以相乘”不是一回事。如果您想要的是“可以成倍增加”,那么您需要一个协议来定义其语义(就像 Numeric 所做的那样),而不仅仅是语法。

标签: swift generics protocols


【解决方案1】:

您可以使用现有的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
}

【讨论】:

    【解决方案2】:

    你可以这样写。

    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 的回答)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-18
      • 1970-01-01
      • 2011-06-11
      • 2011-05-30
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      相关资源
      最近更新 更多