我做了一点" Angle"枚举,以便我可以使用不同的可互换角度格式进行编程:
enum Angle {
case Radians(CGFloat)
case Degrees(CGFloat)
case Rotations(CGFloat)
}
我发现这种方法有一些冗余的样板代码。例如,我想添加一个刚刚返回原始底层关联float的计算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 enum,但这样做会让我不必在那里重复自己吗?
另一个类似的例子是我实现了*
函数:
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)
}
}
似乎应该有一种更简单的方式来表达:"使用我的相关值生成相同的枚举类型乘以标量参数"。
(我不确定我在这个问题上有一个好头衔,随时改善/建议更好)
答案 0 :(得分:2)
这是一个有趣的案例:enum以某种方式不是正确的数据类型,因为该值不是弧度或度数,两者都只是角度而不是真正不同的东西。另外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
哦,至于你原来问题的答案:不,你不能。
答案 1 :(得分:2)
在较新版本的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
}
答案 2 :(得分:0)
基于@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)
}