我可以将Swift枚举中的不同关联值绑定到相同的var吗? [英] Can I bind different associated values in a Swift enum to the same var?

查看:108
本文介绍了我可以将Swift枚举中的不同关联值绑定到相同的var吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 枚举角度{
case Radians(CGFloat)
case度(CGFloat)
case轮换(CGFloat)
}

我发现使用这种方法有一些冗余的样板代码。例如,我想添加一个刚刚返回原始底层关联浮点的计算var:

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

要更改为:

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

我希望这将是聪明的,意识到只有解决一个匹配,所以冲突是可以忽略的。但没有这样的设备。编译器说,它无法解决两个 let值之间的冲突。

所以有一点惯用的聪明我没有发现与Swift枚举,这将使它,所以我不必重复自己那么多在那里?



另一个类似的例子,是当我执行 * 函数:

  func *(lhs:Angle,rhs :CGFloat) - >角度{
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:返回180.0 / M_PI
case轮换:返回1/2 / M_PI
}
}
}

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

func *(var lhs:Angle,rhs:Double) - >角度{
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

哦,对于你原来的问题的答案:不,你不能。


I made a little "Angle" enum so that I could program with different interchangeable angular formats:

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

I find that there's some redundant boilerplate code with this approach though. For example, I wanted to add a computed var that just returned the raw underlying associated float:

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

I tried to change that to read:

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

I hoped it would be clever enough to realize it was only ever going to resolve one match, so the conflict was ignorable. But no such device. Compiler says it can't resolve the conflict between the two let value statements.

So is there a bit of idiomatic cleverness I haven't discovered with Swift enum's yet that would make it so I don't have to repeat myself so much there?

Another similar example, was when I implemented the * function:

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)
    }
}

It seems like there should be a simpler way to express that: "Make the same enum type with my associated value times the scalar argument".

(I'm not sure I've got a good title on this question, feel free to improve/suggest better)

解决方案

That's an interesting case: An enum somehow isn't the right data type, because the value isn't either in radians or in degrees, both are just angles and not really different things. Also typealias Radians = Double wouldn't work because there's no unit safety.

Maybe you can use something like this though:

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

Oh and as for the answer to your original question: No you cannot.

这篇关于我可以将Swift枚举中的不同关联值绑定到相同的var吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆