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

我可以将Swift枚举中的不同关联值绑定到同一个var吗?,swift,enums,swift2,Swift,Enums,Swift2,我制作了一个小小的“角度”枚举,这样我就可以用不同的可互换角度格式进行编程: enum Angle { case Radians(CGFloat) case Degrees(CGFloat) case Rotations(CGFloat) } 我发现这种方法有一些冗余的样板代码。例如,我想添加一个刚刚返回原始基础关联浮点值的计算var: var raw:CGFloat { switch self { case let .Radians(value):

我制作了一个小小的“角度”枚举,这样我就可以用不同的可互换角度格式进行编程:

enum Angle {
    case Radians(CGFloat)
    case Degrees(CGFloat)
    case Rotations(CGFloat)
}
我发现这种方法有一些冗余的样板代码。例如,我想添加一个刚刚返回原始基础关联浮点值的计算var:

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)
    }
}
似乎应该有一种更简单的方式来表示:“使用我的关联值乘以标量参数,使相同的枚举类型”


(我不确定我在这个问题上是否有一个好标题,请随意改进/提出更好的建议)

这是一个有趣的案例:枚举某种程度上不是正确的数据类型,因为值不是以弧度或度数表示的,两者都只是角度,并不是真正不同的东西。另外,
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

哦,至于你最初问题的答案:不,你不能。

根据@Kametrixom的回答,我最终为这个特殊的“角度”建模问题做了如下工作:

import UIKit
import CoreGraphics

let Tau = CGFloat(2 * M_PI)

struct Angle {
    enum Unit:CGFloat {
        case Radians = 1.0
        case Degrees = 57.29577951309314 // 360.0 / Tau
        case Rotations = 6.28318530717959 //Tau
    }
    var raw:CGFloat = 0.0
    var unit:Unit = .Radians

    func convert(anotherUnit:Unit) -> Angle {
        return self.unit == anotherUnit ? self : Angle(raw: self.raw * self.unit.rawValue / anotherUnit.rawValue, unit: anotherUnit)
    }

    var radians:Angle {
        return self.convert(.Radians)
    }

    var degrees:Angle {
        return self.convert(.Degrees)
    }

    var rotations:Angle {
        return self.convert(.Rotations)
    }

    var cos:CGFloat {
        return CoreGraphics.cos(self.radians.raw)
    }

    var sin:CGFloat {
        return CoreGraphics.sin(self.radians.raw)
    }

    var half:Angle {
        return self / 2
    }
}

extension Angle: Comparable {}

func < (lhs:Angle, rhs:Angle) -> Bool {
    return lhs.radians.raw < rhs.radians.raw
}

func == (lhs:Angle, rhs:Angle) -> Bool {
    return lhs.radians.raw == rhs.radians.raw
}

func + (lhs:Angle, rhs:Angle) -> Angle {
    let other = rhs.convert(lhs.unit)
    return Angle(raw: lhs.raw + other.raw, unit: lhs.unit)
}

func - (lhs:Angle, rhs:Angle) -> Angle {
    let other = rhs.convert(lhs.unit)
    return Angle(raw: lhs.raw - other.raw, unit: lhs.unit)
}

func * (lhs:CGFloat, rhs:Angle) -> Angle {
    return rhs * lhs
}

func * (lhs:Angle, rhs:CGFloat) -> Angle {
    return Angle(raw: lhs.raw * rhs, unit: lhs.unit)
}

func / (lhs:Angle, rhs:CGFloat) -> Angle {
    return Angle(raw: lhs.raw / rhs, unit: lhs.unit)
}
导入UIKit
导入核心图形
设Tau=CGFloat(2*M_π)
结构角{
枚举单位:CGFloat{
外壳弧度=1.0
外壳度=57.29577951309314//360.0/Tau
案例旋转=6.28318530717959//Tau
}
原始变量:CGFloat=0.0
变量单位:单位=.Radians
func转换(另一个单位:单位)->角度{
返回self.unit==anotherUnit?self:Angle(原始:self.raw*self.unit.rawValue/anotherUnit.rawValue,单位:anotherUnit)
}
弧度:角度{
返回self.convert(.弧度)
}
变量度:角度{
返回self.convert(.Degrees)
}
变量旋转:角度{
返回self.convert(.Rotations)
}
var cos:CGFloat{
返回CoreGraphics.cos(自弧度原始值)
}
var-sin:CGFloat{
返回CoreGraphics.sin(自弧度原始值)
}
变量半:角度{
返回自我/2
}
}
延伸角:可比{}
func<(左:角度,右:角度)->Bool{
返回左弧度原始值<右弧度原始值
}
func==(左:角度,右:角度)->Bool{
返回lhs.radians.raw==rhs.radians.raw
}
func+(左:角度,右:角度)->角度{
让其他=右侧换算(左侧单位)
返回角(原始值:lhs.raw+其他.raw,单位:lhs.unit)
}
func-(左:角度,右:角度)->角度{
让其他=右侧换算(左侧单位)
返回角(原始:lhs.raw-其他.raw,单位:lhs.unit)
}
func*(左:CGFloat,右:角度)->角度{
返回右*左
}
func*(左:角度,右:CGFloat)->角度{
返回角(原始:左S.raw*rhs,单位:左S.unit)
}
func/(左:角度,右:CGFloat)->角度{
返回角(原始:左侧原始/右侧,单位:左侧单位)
}

在较新版本的Swift中,如果值的类型相同,则现在可以执行此操作:

enum Foo{
案例栏(内部),bas(内部)
}
var this=.random()?Foo.bar(5):Foo.bas(5)
换这个{
case.bar(let-foo),.bas(let-foo):print(foo)//始终打印:5
}
您甚至可以这样做:

enum Foo{
案例栏(Int,Int),bas(Int,Int)
}
var this=.random()?Foo.bar(5):Foo.bas(5)
换这个{
case.bar(let-foo,let-bat),.bas(let-foo,let-bat):print(foo,bat)//始终打印:5
}

谢谢,这帮了大忙。它把我引向了正确的方向。我会在下面的一个单独的“答案”中写下我最终所做的事情。