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

xxslljrj  于 2022-11-06  发布在  Swift
关注(0)|答案(3)|浏览(241)

我做了一个小的“Angular ”枚举,这样我就可以用不同的可互换Angular 格式编程:

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语句之间的冲突。
那么,是不是有一点我还没有发现的习惯上的聪明,这将使我不必在那里重复自己这么多?
另一个类似的例子是当我实现*函数时:

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

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

  • (我不确定我是否有一个好的题目,请随时改进/提出更好的建议)*
lnvxswe2

lnvxswe21#

这是一个有趣的案例:枚举不是正确的数据类型,因为值既不是弧度也不是度,两者都只是Angular ,并不是真正不同的东西。此外,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

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

rqcrx0a6

rqcrx0a62#

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

enum Foo {
    case bar(Int),  bas(Int)
}

var this = .random() ? Foo.bar(5) : Foo.bas(5)
switch this {
    case .bar(let foo), .bas(let foo): print(foo) // Always prints: 5
}

您甚至可以这样做:

enum Foo {
    case bar(Int, Int),  bas(Int, Int)
}

var this = .random() ? Foo.bar(5) : Foo.bas(5)
switch this {
    case .bar(let foo, let bat), .bas(let foo, let bat): print(foo, bat) // Always prints: 5 5
}
tgabmvqs

tgabmvqs3#

基于@Kametrixom的回应,我最终为这个特殊的“Angular ”建模问题做了如下所示:

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

相关问题