带存储字段的Swift枚举?
所以,我一直在寻找一个解决这个问题的方法大约有两天了。我翻阅了Swift文档,尝试了许多不同的google/stack overflow搜索,直接随机编写代码,但都没有用。我想问题的一部分是我不知道怎么用词。。。很抱歉,这让人困惑,但希望我附加的代码能澄清这一点 无论如何,我想知道是否有可能在一个枚举中有一个私有字段,这样每个枚举值都有它自己的值。我不是在问扩展另一个类,也不是在问相关的值。不幸的是,我还没有在网上看到任何关于Swift是否允许这样做的信息,以及如何做到这一点的信息。为了突出我的问题,我正在尝试用Swift重新创建以下Java代码:带存储字段的Swift枚举?,swift,enums,Swift,Enums,所以,我一直在寻找一个解决这个问题的方法大约有两天了。我翻阅了Swift文档,尝试了许多不同的google/stack overflow搜索,直接随机编写代码,但都没有用。我想问题的一部分是我不知道怎么用词。。。很抱歉,这让人困惑,但希望我附加的代码能澄清这一点 无论如何,我想知道是否有可能在一个枚举中有一个私有字段,这样每个枚举值都有它自己的值。我不是在问扩展另一个类,也不是在问相关的值。不幸的是,我还没有在网上看到任何关于Swift是否允许这样做的信息,以及如何做到这一点的信息。为了突出我的
// Java
public enum Direction {
LEFT(0, -1), RIGHT(0, 1), UP(-1, 0), DOWN(1, 0);
private final int rowChange, colChange;
Direction(int rowChange, int colChange) {
this.rowChange = rowChange;
this.colChange = colChange;
}
public int rowChange() {
return this.rowChange;
}
public int colChange() {
return this.colChange;
}
}
这就是我目前所拥有的,它是有效的,但我更希望它有存储值,而不是通过每个可能的情况进行切换
// Swift
public enum Direction {
case left, right, up, down
public func rowChange() -> Int {
switch self {
case .left:
return 0
case .right:
return 0
case .up:
return -1
case .down:
return 1
}
}
public func colChange() -> Int {
switch self {
case .left:
return -1
case .right:
return 1
case .up:
return 0
case .down:
return 0
}
}
}
打开
self
是标准方式。通过让枚举从Int继承(或字符串是另一种常见情况),可以将单个值分配给枚举。但对于这样的两个值,切换将是正常的方式
也许可以考虑使用结构体来代替?大概是这样的:
struct Direction: Equatable {
let row: Int
let column: Int
static let left = Direction(row: 0, column: -1)
static let right = Direction(row: 0, column: 1)
static let up = Direction(row: -1, column: 0)
static let down = Direction(row: 1, column: 0)
private init() {
// Just to disable empty initialisation, not actually used.
self.row = 0
self.column = 0
}
private init(row: Int, column: Int) {
self.row = row
self.column = column
}
}
let direction = Direction.left
let row = direction.row
let column = direction.column
public struct PointOffset {
public var dX, dY: Int
static func left (by distance: Int) { return self.init(dX: -distance, dY: 0) }
static func right(by distance: Int) { return self.init(dX: +distance, dY: 0) }
static func up (by distance: Int) { return self.init(dX: 0, dY: +distance) }
static func down (by distance: Int) { return self.init(dX: 0, dY: -distance) }
}
print(Direction.left.rawValue) // --> (0, -1)
print(Direction.left.rowChange) // --> 0
print(Direction.left.colChange) // --> -1
可以这样访问它:
struct Direction: Equatable {
let row: Int
let column: Int
static let left = Direction(row: 0, column: -1)
static let right = Direction(row: 0, column: 1)
static let up = Direction(row: -1, column: 0)
static let down = Direction(row: 1, column: 0)
private init() {
// Just to disable empty initialisation, not actually used.
self.row = 0
self.column = 0
}
private init(row: Int, column: Int) {
self.row = row
self.column = column
}
}
let direction = Direction.left
let row = direction.row
let column = direction.column
public struct PointOffset {
public var dX, dY: Int
static func left (by distance: Int) { return self.init(dX: -distance, dY: 0) }
static func right(by distance: Int) { return self.init(dX: +distance, dY: 0) }
static func up (by distance: Int) { return self.init(dX: 0, dY: +distance) }
static func down (by distance: Int) { return self.init(dX: 0, dY: -distance) }
}
print(Direction.left.rawValue) // --> (0, -1)
print(Direction.left.rowChange) // --> 0
print(Direction.left.colChange) // --> -1
此外,如果目标是使用模式匹配,那么当结构从equalable
继承时,您可以编写如下内容:
switch direction {
case .left:
break
case .right:
break
case .up:
break
case .down:
break
default:
break
}
打开
self
可以保证为枚举中的每个案例返回一个有效值,并且如果向枚举中添加新值,它将保护您,因为只有为新值添加案例,代码才会编译。不要使用func,请使用属性:
public enum Direction {
case left, right, up, down
var rowChange: Int {
switch self {
case .left: return 0
case .right: return 0
case .up: return -1
case .down: return 1
}
}
var colChange: Int {
switch self {
case .left: return -1
case .right: return 1
case .up: return 0
case .down: return 0
}
}
}
调用它的示例:
let list: [Direction] = [.left, .right, .up, .down]
for e in list {
print("ROW changed = \(e.rowChange)")
print("COL changed = \(e.colChange)")
}
您的解决方案基本上是正确的,我将避免使用,并返回一个
(dX:Int,dY:Int)
元组,或者甚至类似于点偏移量
结构。我还将使用computed属性,而不是无参数方法
public enum Direction {
case left, right, up, down
public var offset: (dX: Int, dY: Int) {
switch self {
case .left: return (dX: -1, dY: 0)
case .right: return (dX: +1, dY: 0)
case .up: return (dX: 0, dY: +1)
case .down: return (dX: 0, dY: -1)
}
}
}
如果您设想需要的方向不是单一的距离单位,那么我建议您从enum
切换到struct
,并执行以下操作:
struct Direction: Equatable {
let row: Int
let column: Int
static let left = Direction(row: 0, column: -1)
static let right = Direction(row: 0, column: 1)
static let up = Direction(row: -1, column: 0)
static let down = Direction(row: 1, column: 0)
private init() {
// Just to disable empty initialisation, not actually used.
self.row = 0
self.column = 0
}
private init(row: Int, column: Int) {
self.row = row
self.column = column
}
}
let direction = Direction.left
let row = direction.row
let column = direction.column
public struct PointOffset {
public var dX, dY: Int
static func left (by distance: Int) { return self.init(dX: -distance, dY: 0) }
static func right(by distance: Int) { return self.init(dX: +distance, dY: 0) }
static func up (by distance: Int) { return self.init(dX: 0, dY: +distance) }
static func down (by distance: Int) { return self.init(dX: 0, dY: -distance) }
}
print(Direction.left.rawValue) // --> (0, -1)
print(Direction.left.rowChange) // --> 0
print(Direction.left.colChange) // --> -1
您可以遵循
RawRepresentable
并使用(Int,Int)
作为Self.RawValue
:
enum Direction : RawRepresentable {
case left, right, up, down
var rawValue : (Int, Int) {
switch self {
case .left: return (0, -1)
case .right: return (0, 1)
case .up: return (-1, 0)
case .down: return (1, 0)
}
}
init?(rawValue: (Int, Int)) {
switch rawValue {
case (0, -1): self = .left
case (0, 1): self = .right
case (-1, 0): self = .up
case (1, 0): self = .down
case (_, _): return nil
}
}
var rowChange : Int { return self.rawValue.0 }
var colChange : Int { return self.rawValue.1 }
}
然后你可以这样使用它:
struct Direction: Equatable {
let row: Int
let column: Int
static let left = Direction(row: 0, column: -1)
static let right = Direction(row: 0, column: 1)
static let up = Direction(row: -1, column: 0)
static let down = Direction(row: 1, column: 0)
private init() {
// Just to disable empty initialisation, not actually used.
self.row = 0
self.column = 0
}
private init(row: Int, column: Int) {
self.row = row
self.column = column
}
}
let direction = Direction.left
let row = direction.row
let column = direction.column
public struct PointOffset {
public var dX, dY: Int
static func left (by distance: Int) { return self.init(dX: -distance, dY: 0) }
static func right(by distance: Int) { return self.init(dX: +distance, dY: 0) }
static func up (by distance: Int) { return self.init(dX: 0, dY: +distance) }
static func down (by distance: Int) { return self.init(dX: 0, dY: -distance) }
}
print(Direction.left.rawValue) // --> (0, -1)
print(Direction.left.rowChange) // --> 0
print(Direction.left.colChange) // --> -1
不相关的注意:应该使用
var列:Int{…}
而不是func colChange()->Int{…}
。由于这是一个O(1)操作,事实上在Swift中编写它的方式是使用属性,而不是函数。可能重复感谢大家的反馈-我对Swift还是比较新的,所以我感谢大家的帮助。我将把它们转换为计算属性。。。Swift不允许我在Java中经常使用的东西,这有点奇怪,但我想开关也可以正常工作。struct
方法的问题是,可以使用其他值创建其他方向。您至少应该将init
设置为私有,以便只有4个静态项可见。并将这两个属性设置为只读的公共属性。@rmaddy关于private init的观点很好,但是列/行属性已经是只读的,所以我不确定您的意思。不管怎样,我只是提供OP一个switch语句的替代方案。更不用说这两个属性了。我一时忘记了它们是不可写的,因为它们是let
.Hm,非常有趣-我甚至没有考虑过struct方法。谢谢你的意见!