如何访问一个斯威夫特枚举关联值switch语句之外
enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
}
let leftEdge = Line.Horizontal(0.0)
let leftMaskRightEdge = Line.Horizontal(0.05)
如何访问,也就是说,相关值,直接lefEdge
的,不使用switch语句?
let noIdeaHowTo = leftEdge.associatedValue + 0.5
这甚至没有编译!
我看了一下theseSOquestions但没有一个答案似乎解决了这个问题。
noIdeaHowTo
上面的非编译行应该是一行代码,但因为可以是任何类型,所以我甚至无法看到用户代码在le enum本身中如何编写“generic”get或associatedValue方法。
我结束了这一点,但它是毛,而需要我每次我添加/修改的情况下,时间再看看代码...
enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
var associatedValue: CGFloat {
get {
switch self {
case .Horizontal(let value): return value
case .Vertical(let value): return value
}
}
}
}
任何指针的人?
正如其他人所指出的那样,这是目前在斯威夫特2种可能:
import CoreGraphics
enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
}
let min = Line.Horizontal(0.0)
let mid = Line.Horizontal(0.5)
let max = Line.Horizontal(1.0)
func doToLine(line: Line) -> CGFloat? {
if case .Horizontal(let value) = line {
return value
}
return .None
}
doToLine(min) // prints 0
doToLine(mid) // prints 0.5
doToLine(max) // prints 1
你会如何实现它的方式,它适用于任何枚举和任何情况? –
@RodrigoRuiz我向你推荐Arkku的回答。你想要一个包含一个枚举和一个值的结构,而不仅仅是一个枚举。 – uliwitness
我想你可能会尝试使用enum
来实现它不打算用于的目的。通过switch
的方式来访问关联的值的方法的确如此,因为switch
总是处理每个可能的成员案例enum
。在enum
的
不同成员可以具有不同的相关值(例如,你可以在你的enum Line
Diagonal(CGFloat, CGFloat)
和Text(String)
),所以你必须确认你正在处理,然后才能访问相关值的情况。例如,考虑:
enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
case Diagonal(CGFloat, CGFloat)
case Text(String)
}
var myLine = someFunctionReturningEnumLine()
let value = myLine.associatedValue // <- type?
你怎么竟敢从myLine
获得相关值时,你可能会处理CGFloat
,String
,或 CGFloat
S'这就是为什么你需要switch
首先发现你有哪些case
。
在您的特定情况下,它听起来就像你可能是一个class
或struct
为Line
,那么这可能会存储CGFloat
,也有一个enum
属性Vertical
和Horizontal
更好。或者,您可以将Vertical
和Horizontal
作为单独的类别进行建模,其中Line
是一个协议(例如)。
是。我绝对认为这需要语言支持。这是一种情况,其中回报值不应该是关于变化的类型,而是不同的元数。返回(1)case y ... return(0,“stuff”)case z ... return(-1,3.14,[“for”,“good”, “测量”])。编译器直接支持这可能更好。嗅探雷达的方式... – verec
为什么这是不可能的已经回答了,所以这只是一个建议。你为什么不像这样实施它。我的意思是枚举和结构都是值类型。
enum Orientation {
case Horizontal
case Vertical
}
struct Line {
let orientation : Orientation
let value : CGFloat
init(_ orientation: Orientation, _ value: CGFloat) {
self.orientation = orientation
self.value = value
}
}
let x = Line(.Horizontal, 20.0)
// if you want that syntax 'Line.Horizontal(0.0)' you could fake it like this
struct Line {
let orientation : Orientation
let value : CGFloat
private init(_ orientation: Orientation, _ value: CGFloat) {
self.orientation = orientation
self.value = value
}
static func Horizontal(value: CGFloat) -> Line { return Line(.Horizontal, value) }
static func Vertical(value: CGFloat) -> Line { return Line(.Vertical, value) }
}
let y = Line.Horizontal(20.0)
与SWIFT 2有可能获得相关的值使用反射(只读)。
为了简化操作,只需将下面的代码添加到项目中,并使用EVAssociated协议扩展您的枚举。
public protocol EVAssociated {
}
public extension EVAssociated {
public var associated: (label:String, value: Any?) {
get {
let mirror = Mirror(reflecting: self)
if let associated = mirror.children.first {
return (associated.label!, associated.value)
}
print("WARNING: Enum option of \(self) does not have an associated value")
return ("\(self)", nil)
}
}
}
然后你就可以使用代码访问.asociated值是这样的:
class EVReflectionTests: XCTestCase {
func testEnumAssociatedValues() {
let parameters:[EVAssociated] = [usersParameters.number(19),
usersParameters.authors_only(false)]
let y = WordPressRequestConvertible.MeLikes("XX", Dictionary(associated: parameters))
// Now just extract the label and associated values from this enum
let label = y.associated.label
let (token, param) = y.associated.value as! (String, [String:Any]?)
XCTAssertEqual("MeLikes", label, "The label of the enum should be MeLikes")
XCTAssertEqual("XX", token, "The token associated value of the enum should be XX")
XCTAssertEqual(19, param?["number"] as? Int, "The number param associated value of the enum should be 19")
XCTAssertEqual(false, param?["authors_only"] as? Bool, "The authors_only param associated value of the enum should be false")
print("\(label) = {token = \(token), params = \(param)")
}
}
// See http://github.com/evermeer/EVWordPressAPI for a full functional usage of associated values
enum WordPressRequestConvertible: EVAssociated {
case Users(String, Dictionary<String, Any>?)
case Suggest(String, Dictionary<String, Any>?)
case Me(String, Dictionary<String, Any>?)
case MeLikes(String, Dictionary<String, Any>?)
case Shortcodes(String, Dictionary<String, Any>?)
}
public enum usersParameters: EVAssociated {
case context(String)
case http_envelope(Bool)
case pretty(Bool)
case meta(String)
case fields(String)
case callback(String)
case number(Int)
case offset(Int)
case order(String)
case order_by(String)
case authors_only(Bool)
case type(String)
}
上面的代码是从我的项目https://github.com/evermeer/EVReflection https://github.com/evermeer/EVReflection
您可以使用保护语句访问相关的价值,就像这样。
enum Line {
case Horizontal(Float)
case Vertical(Float)
}
let leftEdge = Line.Horizontal(0.0)
let leftMaskRightEdge = Line.Horizontal(0.05)
guard case .Horizontal(let leftEdgeValue) = leftEdge else { fatalError() }
print(leftEdgeValue)
我认为你所做的是正确的(计算属性,即)。枚举可以有任何类型的关联值,更重要的是任何数量。我没有看到苹果如何在不迫使我们陷入无数“as”和“if”的情况下提供速记访问。 – courteouselk
顺便说一句,如果您的枚举具有与每种情况关联的CGFloat,则可以考虑使用原始值而不是关联。 – courteouselk
@AntonBronnikov原始值是常量,它们必须是唯一的,即不能有两个具有不同值的“水平”实例。 – Arkku