一尘不染

我可以将Swift枚举中的不同关联值绑定到同一var吗?

swift

我做了一个小“ Angle”枚举,以便可以使用不同的可互换角度格式进行编程:

enum Angle {
    case Radians(CGFloat)
    case Degrees(CGFloat)
    case Rotations(CGFloat)
}

我发现这种方法有些多余的样板代码。例如,我想添加一个计算的var,它只返回原始底层关联的float:

var raw:CGFloat {
    switch self {
    case let .Radians(value):
        return value
    case let .Degrees(value):
        return value
    case let .Rotations(value):
        return value
    }
}

我试图将其更改为:

case .Radians(let value), .Degrees(let value):
    return value

我希望它足够聪明,以至于只能解决一场比赛,所以这场冲突是可忽略的。但是没有这样的设备。编译器说它不能解决两个let value语句之间的冲突。

那么我在Swift枚举中还没有发现一些惯用的聪明之处吗,那么它就可以做到了,这样我就不必在这里重复太多了?

另一个类似的例子是当我实现*函数时:

func * (lhs:Angle, rhs:CGFloat) -> Angle {
    switch lhs {
    case .Radians:
        return .Radians(lhs.raw * rhs)
    case .Degrees:
        return .Degrees(lhs.raw * rhs)
    case .Rotations:
        return .Rotations(lhs.raw * rhs)
    }
}

似乎应该有一种更简单的表达方式:“将相同的枚举类型与我的关联值乘以标量参数”。

(我不确定我在这个问题上是否有很好的头衔,可以随时改善/建议更好)


阅读 247

收藏
2020-07-07

共1个答案

一尘不染

这是一个有趣的情况:枚举不是某种正确的数据类型,因为该值既不是弧度也不是以度为单位,两者都只是角度而不是真正不同的东西。也typealias Radians = Double没有用,因为没有单元安全。

也许您可以使用如下所示的方法:

import Darwin

struct Angle {
    enum Unit {
        case Radians
        case Degrees
        case Rotations

        var radiansFactor : Double {
            switch self {
            case Radians: return 1
            case Degrees: return 180.0 / M_PI
            case Rotations: return 1 / 2 / M_PI
            }
        }
    }

    var unit : Unit {
        didSet {
            value /= oldValue.radiansFactor
            value *= unit.radiansFactor
        }
    }
    var value : Double
}

func * (var lhs: Angle, rhs: Double) -> Angle {
    lhs.value *= rhs
    return lhs
}

var angle = Angle(unit: .Degrees, value: 180)

angle.value             // 180.0
angle.unit = .Radians
angle.value             // 3.141592...
angle.unit = .Rotations
angle.value             // 0.5

哦,关于您的原始问题的答案:不,您不能。

2020-07-07