Swift Enum Inheritance

Swift enum inheritance

In Swift language, we have Structs, Enum and Classes. Struct and Enum are passed by copy but Classes are passed by reference. Only Classes support inheritance, Enum and Struct don't.

So to answer your question, you can't have inheritance with Enum (and Struct types). Have a look here:

stackOverflow difference classes vs structs

Can an enum contain another enum values in Swift?


Details

  • Swift 4, 3
  • Xcode 10.2.1 (10E1001), Swift 5 (Last revision of this post)

Solution

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

Full Sample

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)

Result

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

Swift : How to use enum variable from super class?

It looks like the value depends on the class, i.e., you don't need to change its value during the lifetime of an instance. If this is the case, you can change it to a computed property:

var animalType: AnimalsType { return .none }

And

override var animalType: AnimalsType { return .underwater }

Another possibility is to define the stored property once and assign the initial value in init for each class.

Enum in inheritance

How about this approach:

enum Action {
case Attack, Block, Charge, CastSpell, Run
}

class Character {

final func performAction(action: Action) {
if self.allowedActions().contains(action) {
self.executeAction(action);
}
}

func allowedActions() -> [Action] {
// to be overriden in subclasses
return []
}

func executeAction(action: Action) {
// this will also be overriden in subclasses
}
}

class Warrior: Character {
override func allowedActions() -> [Action] {
return [.Attack, .Block, .Charge]
}

override func executeAction(action: Action) {
// do whatever is needed
}
}

class Wizard: Character {
override func allowedActions() -> [Action] {
return [.Attack, .CastSpell, .Run]
}

override func executeAction(action: Action) {
// do whatever is needed
}
}

You use one enum to hold all possible actions, and you define per subclass which actions are allowed.

This way you can treat all characters the same: ask for the actions they can perform, so you can show a menu for example, and then ask the character to perform that action.

We can go even further, by using structs instead of classes and associated values for enums, this being a more swift-ish approach, but also a little bit more complicated to setup (but more logical).

Is it possible to put a tuple in an enum with Swift?

As pointed out by @MartinR. Also, according to Apple docs, "enumeration cases can specify associated values of any type to be stored along with each different case value". If you want to keep using enum, you may need to do something like:

static func PrintFruit(fruit:FruitTuple.Apple)
{
let shape:String = fruit.shape
let colour:String = fruit.colour

print("Fruit is \(shape) and \(colour)")
}

I'm not certain of what you want, but I guess using typealias could help achieve your goal.

typealias FruitTuple = (shape: String, colour: String)

enum Fruit
{
static let apple = FruitTuple("round" , "red")
static let orange = FruitTuple("round", "orange")
static let banana = FruitTuple("long", "yellow")
}

func printFruit(fruitTuple: FruitTuple)
{
let shape:String = fruitTuple.shape
let colour:String = fruitTuple.colour
}

how to define an array of a particular enum case in swift

All cases of an enum are of the same enum type, so you cannot declare an Array that can only hold a specific case of an enum.

However, you can achieve your goals by creating 2 enums instead of one and making the Menu.submenu enum case take the other enum as its associated value.

enum Menu {
case item(MenuItem)
case submenu([MenuItem])
}

enum MenuItem {
case item(String)
}

Then you can use it like

let menu = Menu.item(.item("main"))
let submenu = Menu.submenu([.item("a"), .item("b")])


Related Topics



Leave a reply



Submit