我可以将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
}
谢谢,这帮了大忙。它把我引向了正确的方向。我会在下面的一个单独的“答案”中写下我最终所做的事情。