Reputation: 10421
I'd like to share some enum properties. Something like:
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
}
}
I see why ActionState
can not inherit from State
(because the state cancelled
has no representation in State
) but I want to still be able to say "ActionState is like State with more options, and ActionState can get inputs that are of type State, because they are also of type ActionState"
I see how I could get the above logic to work with copying the cases in ActionState
and having a switch in the set
function. But I'm looking for a better way.
I know enum can't inherit in Swift, and I've read the protocol answer of swift-enum-inheritance. It doesn't address the need for "inheriting" or including cases from another enum, but only properties and variables.
Upvotes: 19
Views: 20970
Reputation: 111
Even if it is not directly possible to extend an enum as explained in the other answers, you can work around it using raw values. For example:
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
}
}
I think this is the cleanest solution although it requires some code duplication when defining enum. Crucially, you need to make sure that the raw values between State
and ActionState
match.
Upvotes: 0
Reputation: 2610
I had to validate the User License document. Which had two side - front and back. Depending upon the validation document could either be valid or invalid. Also UX was such that it would be active state or inactive state with corresponding colors to display. I ended up making following enum.
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
}
}
}
Which can be referred as -
public var validity: Validity = Validity.pending(.active(.front))
I wish it could have been more clean like -
Validity.pending.active.front
but this is so far the solution for Enum inside of another enum can be.
Swift 5.1, Xcode 11.4.1
Upvotes: 10
Reputation: 25304
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 }
}
Do not to forget to paste the solution code
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
Upvotes: 31