【发布时间】:2017-03-31 23:46:45
【问题描述】:
注意:这与我昨天在 Stackoverflow 上发布的 another one 基本相同。但是,我认为我在那个问题中使用了一个糟糕的例子,它并没有完全归结为我所想的本质。由于对该原始帖子的所有回复都提到了第一个问题,我认为将新示例放在一个单独的问题中可能是一个更好的主意 - 无意重复。
模拟可以移动的游戏角色
让我们定义一个用于简单游戏的方向枚举:
enum Direction {
case up
case down
case left
case right
}
现在在游戏中我需要两种角色:
- 一个只能左右移动的
HorizontalMover。
← → - 一个只能上下移动的
VerticalMover。
↑ ↓
它们都可以移动,所以它们都实现了
protocol Movable {
func move(direction: Direction)
}
那么让我们定义两个结构体:
struct HorizontalMover: Movable {
func move(direction: Direction)
let allowedDirections: [Direction] = [.left, .right]
}
struct VerticalMover: Movable {
func move(direction: Direction)
let allowedDirections: [Direction] = [.up, .down]
}
问题
...使用这种方法,我仍然可以将不允许的值传递给move() 函数,例如以下调用将是有效的:
let horizontalMover = HorizontalMover()
horizontalMover.move(up) // ⚡️
当然,我可以在 move() 函数内部检查此 Mover 类型是否允许传递的 direction,否则抛出错误。但是因为我确实知道在编译时允许哪些情况我也希望在编译时进行检查。
所以我真正想要的是:
struct HorizontalMover: Movable {
func move(direction: HorizontalDirection)
}
struct VerticalMover: Movable {
func move(direction: VerticalDirection)
}
其中HorizontalDirection 和VerticalDirection 是Direction 枚举的子集枚举。
像这样独立定义两个方向类型没有多大意义,没有任何共同的“祖先”:
enum HorizontalDirection {
case left
case right
}
enum VerticalDirection {
case up
case down
}
因为我必须一遍又一遍地重新定义相同的情况,这些情况对于每个表示方向的枚举在语义上是相同的。例如。如果我添加另一个可以向任何方向移动的角色,我还必须实现大方向枚举(如上所示)。然后我在HorizontalDirection 枚举中有一个left 案例,在一般Direction 枚举中有一个left 案例,它们彼此不了解,这不仅丑陋,而且在分配和分配时成为一个真正的问题利用我必须在每次枚举中重新分配的原始值。
那么有没有办法解决这个问题?
我可以像这样将一个枚举定义为另一个枚举的案例的子集吗?
enum HorizontalDirection: Direction {
allowedCases:
.left
.right
}
【问题讨论】:
标签: swift enums subset restriction