协议(protocol)的 Swift 运算符

标签 swift

假设我有两个符合协议(protocol)的结构,

protocol NumberType {
    var doubleValue: Double { get }
}

struct Rational: NumberType {
    let numerator: Int
    let denominator: Int
    var doubleValue: Double { get { return Double(numerator) / Double(denominator) } }
}

struct FixedPoint: NumberType {
    let value: Double
    var doubleValue: Double { get { return value } }
}

我想为 NumberType 定义算术运算符,它将依次返回 NumberType

func *(lhs: NumberType, rhs: NumberType) -> NumberType { return FixedPoint(lhs.doubleValue * rhs.doubleValue) }

但我还想添加更具体的运算符,因此当两者都是 Rational 时,我返回一个 Rational

func *(lhs: Rational, rhs: Rational) -> NumberType { return Rational(...) }

有没有比每个运算符都有一个执行所有类型检查的 super 函数更优雅的方法来做到这一点?

编辑

您应该能够将 FixedPoint 乘以 Rational,因为它们都符合 NumberType。

重载策略将不起作用,因为如果我执行 a * b * c,其中所有值都是 Rationala * b< 的结果NumberType,因此 (a * b) * c 将退回到使用通用 NumberType 乘法运算符。我会在这里失去我的精度。

我不介意能够乘以 DoublesInts

进一步编辑

假设最通用的情况总是返回一个 FixedPoint 是不正确的。我在这里展示了基本用法,但是如果你有一个等于 0FixedPoint 和另一个 Rational,并且你想添加它们,在最通用的情况下,您可以获得 Rational 是可行的。

最佳答案

你可以在这里使用泛型......

如果你像这样定义协议(protocol)......

protocol NumberType {    
    var doubleValue: Double { get }

    init(doubleValue double: Double)
}

然后你可以定义一个函数...

func *<T: NumberType>(lhs: T, rhs: T) -> T {
    return T(doubleValue: lhs.doubleValue * rhs.doubleValue)
}

这将允许您将此函数用于任何类型的对象,只要它符合 NumberType。唯一需要注意的是 lhsrhs 必须是同一类型。

然后在每个 NumberType 的实现中,您可以定义 init 如何工作...

struct FixedPoint: NumberType {
    let value: Double
    var doubleValue: Double { get { return value } }

    init(doubleValue double: Double) {
        // this implementation may not be practical for things like Rationals etc...
        self.value = double
    }
}

如果没有一些创建 NumberTypes 的通用方法,那么您将不得不对该函数的工作方式进行多次实现,因此您需要根据输入内容创建多个实例的方法。

关于协议(protocol)的 Swift 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42201960/

相关文章:

ios - 在 xcode/swift 中使用位置管理器获取用户的当前位置时,我得到的值为 nil。有什么建议么?

ios - Xcode 10.0 GM - dyld : lazy symbol binding failed: can't resolve symbol ___cxa_guard_acquire crash. 在那之前工作正常

ios - 无法使用 Kingfisher 显示 url 中的图像

ios - SKSpriteNode 子类化 swift

ios - 从 KeyChain 保存和加载 | swift

swift - 尝试修复典型的 find nil while unwrapping 错误

ios - UIWebview 总是以水平滚动加载

ios - GCD设置线程间的调度/优先级

ios - 展开一个可选值 nil

ios - 如何在swift 4中获取从特定字符到字符串末尾的子字符串?