Swift中的枚举可以包含另一个枚举的值吗?

17

我想分享一些枚举属性。就像这样:

enum State {
  case started
  case succeeded
  case failed
}

enum ActionState {
  include State // what could that be?
  case cancelled
}

class Action {
  var state: ActionState = .started

  func set(state: State) {
    self.state = state
  }

  func cancel() {
    self.state = .cancelled
  }
}

我明白为什么 ActionState 不能继承自 State (因为状态 cancelledState 中没有代表),但我还是想说 "ActionState 就像是有更多选项的 State,ActionState 可以接收类型为 State 的输入,因为它们也是 ActionState 类型"

我知道在 Swift 中枚举类型无法继承,我已经阅读了 swift-enum-inheritance 的协议回答。它没有解决“继承”或包含另一个枚举类型中的情况,只能继承属性和变量。

我看到如何通过复制 ActionState 中的 case 并在 set 函数中使用 switch 语句来实现上述逻辑。但我正在寻找更好的方法。


可能是Swift枚举继承的重复问题。 - Jim Stewart
1
在答案中往下读一点。有一个还不错的解决方法来弥补没有直接方法的缺陷。 - Jim Stewart
不确定。解决方法使用协议使枚举从协议继承属性/函数,但我不知道如何使用它使枚举从另一个枚举继承情况(无论这里的继承是什么)。 - Guig
看起来最终的答案是否定的。对我来说,这听起来非常像需要使用类而不是枚举的明显情况——当你真正需要继承时。 - user7014451
我并不需要继承,而是更需要包含,无论那是什么。继承实际上是没有意义的,因为假设这些是类,cancelled状态在State范围内没有相应的等价物。换句话说,ActionState并不总是可以表示为State,而反之则成立(但让StateActionState继承会非常奇怪)。我理解你的观点,最终答案可能是不需要继承。 - Guig
3个回答

29

详情

  • Swift 4, 3
  • Xcode 10.2.1 (10E1001), Swift 5(本文最新修订版)

解决方案

enum State {
    case started, succeeded, failed
}

enum ActionState {
    case state(value: State), cancelled
}

class Action {
    var state: ActionState = .state(value: .started)
    func set(state: State) { self.state = .state(value: state) }
    func cancel() { state = .cancelled }
}

完整示例

不要忘记粘贴解决方案代码

import Foundation

extension Action: CustomStringConvertible {
    var description: String {
        var result = "Action - "
        switch state {
            case .state(let value): result += "State.\(value)"
            case .cancelled: result += "cancelled"
        }
        return result
    }
}

let obj = Action()
print(obj)
obj.set(state: .failed)
print(obj)
obj.set(state: .succeeded)
print(obj)
obj.cancel()
print(obj)

结果

//Action - State.started
//Action - State.failed
//Action - State.succeeded
//Action - cancelled

8

我需要验证用户许可证文档,它有正反两面。根据验证结果,文档可以是有效或无效的。同时,用户体验设计师制定了对应颜色的激活状态和非激活状态。最后我创建了以下枚举类型。

public enum Validity {
    case pending(_ selectState: SelectState)
    case valid(_ selectState: SelectState)
    case invalid(_ selectState: SelectState)
    
    enum SelectState {
      case active(_ side: Side)
      case inactive(_ side: Side)
      
      enum Side {
        case front
        case back
      }
    }
  }

这可以称为 -

public var validity: Validity = Validity.pending(.active(.front))

我希望它能更简洁,像这样 - Validity.pending.active.front 但目前这是嵌套枚举的解决方案。

Swift 5.1,Xcode 11.4.1


0
即使根据其他答案的解释,直接扩展枚举可能是不可能的,但是你可以通过使用原始值来绕过这个问题。例如:
enum State: Int {
  case started
  case succeeded
  case failed
}

enum ActionState: Int {
  case started
  case succeeded
  case failed
  case cancelled
}

class Action {
  var state: ActionState = .started

  func set(state: State) {
    self.state = ActionState(rawValue: state.rawValue)!
  }

  func cancel() {
    self.state = .cancelled
  }
}

我认为这是最干净的解决方案,尽管在定义枚举时需要一些代码重复。关键是,你需要确保 StateActionState 之间的原始值是匹配的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接