Может ли перечисление содержать другие значения перечисления в Swift?

Я хотел бы поделиться некоторыми свойствами перечисления. Что-то вроде:

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 (потому что государство cancelled не имеет представительства в State) но я все еще хочу сказать: "ActionState похож на State с большим количеством опций, и ActionState может получать входные данные, имеющие тип State, поскольку они также имеют тип ActionState"

Я вижу, как я мог заставить вышеупомянутую логику работать с копированием случаев в ActionState и имея переключатель в set функция. Но я ищу лучший путь.

Я знаю, что enum не может наследоваться в Swift, и я прочитал ответ протокола swift-enum-наследования. Он не учитывает необходимость "наследования" или включения дел из другого перечисления, а только свойства и переменные.

3 ответа

Решение

Фиксированный код

import Foundation

enum State {
    case started
    case succeeded
    case failed
}

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

class Action {

    var state: ActionState = .state(value: .started)

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

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

    var description:String {

        var result = "Action "
        switch state {

            case .state(value: .started):
                result += "\(state)"

            case .state(value: _):
                result += "\(state)"

            case .cancelled:
                result += "cancelled"
        }
        return result
    }
}

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

Результат

Мне пришлось проверить документ лицензии пользователя. У которого было две стороны - передняя и задняя. В зависимости от документа проверки может быть действительным или недействительным. Кроме того, UX был таким, что отображалось активное или неактивное состояние с соответствующими цветами. В итоге я сделал следующее перечисление.

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но это пока решение для Enum внутри другого enum может быть.

Swift 5.1, Xcode 11.4.1

Даже если невозможно напрямую расширить перечисление, как описано в других ответах, вы можете обойти это, используя необработанные значения. Например:

      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
  }
}

Я думаю, что это самое чистое решение, хотя оно требует некоторого дублирования кода при определении перечисления. Крайне важно убедиться, что необработанные значения междуStateиActionStateсоответствовать.

Другие вопросы по тегам