---
title: Swift and the Hidden Power of Enums
description: Did you know that you can use enums as building blocks in Swift? Check out these examples.
---

[Avenue Code Snippets](https://blog.avenuecode.com)

# [Swift and the Hidden Power of Enums](https://blog.avenuecode.com/swift-and-the-hidden-power-of-enums)

 Written by [Eduardo Salinas](https://blog.avenuecode.com/author/eduardo-salinas) | 10/30/19 5:00 PM

Enums--or enumerated types--in Swift have been around for a long time, but I never truly explored their potential until I stumbled across [an article](https://appventure.me/guides/advanced_practical_enum_examples/introduction.html) explaining that "enums can define any hierarchically organized data." So I decided to try using enums, not as I had traditionally used them, but as the very foundation of my data. Today, I invite you to explore the potential of these powerful types with me.

We usually use enums as a way to define a finite set of options in a given context, but in the following scenarios, I'll use them as linked lists (which is easy to do, thanks to indirect cases), and as a simplified sort of function builder (similar to how the new SwiftUI framework functions).

Let's show the power of enums by providing two examples: in the first example, we'll use enums instead of structs and classes to build a fun role-playing game, and in the second example, we'll use enums to create an app for model train enthusiasts. 

##### Using Enums to Create a Game

I love games, especially role-playing games. Nothing is better than entering a world of fantasy and taking your character along a perilous journey, watching them grow, and hopefully, not getting them killed along the way. And if enums can define any hierarchical data, then, we should be able to build game components with them.

For example, in our game, we can have an enum define the possible status conditions that our units can have:

**enum** Effect {

    **case** poison

    **case** blind

    **case** burn

    **case** bleed

    **case** freeze

    **case** damage(Int)

    **case** heal(Int)

}

Our units can have an array of effects to indicate what happens to them. This enum can also be used for applying effects when an attack happens. Some attacks, such as swords or axes, would only damage units, while other attacks could poison, bleed, or burn our foes. 

We can construct enums in such a way that they behave like semantic expressions. By chaining enums together, we can construct easy-to-understand definitions for the components in our game. Let’s say we’d like to create the logic for defining different attacks in our game, such as melee attacks or magic attacks. We can divide the attack into three parts: 

- The target

- The effect

- The attack type

So our structure would be something similar to: attack with “type” to “target” for ”effect.“

**TARGET**

We can start by defining an enum for possible targets:

**enum** TargetType {

    **case** ally

    **case** enemy

    **case** unit

}

An attack can be against an enemy, an ally (in the case of a heal spell, for example) or any unit. We can also define a given range constraint:

**enum** Range {

    **case** range(Int)

}

That would limit the range of our attack. We can also define the location of our targets:

**enum** Direction {

    **case** front

    **case** behind

    **case** around

}

And we can even define a constraint to the number or proximity of targets. For example:

**enum** Target {

    **case** target(TargetType, Range)

    **case** all(TargetType, Direction, Range)

}

Now, we can construct a very detailed description of the target, say for a melee weapon:

**let** meleeTarget: Target = .target(.enemy, .inRange(1))

We know that we want to target any enemy that’s within our range. Or if we wanted to perform a massive area-of-effect spell:

**let** spellTarget: Target = .all(.enemy, .around, .inRange(6))

**EFFECT**

But what will our attacks do? Well, we can define a trigger, maybe something that happens only if the hit is successful, or if the target dies. Again we can do all of this with enums:

**enum** TriggerType {

    **case** damage

    **case** hit

    **case** kill

}

The trigger type will tell us when we should trigger the effect of the attack.

**enum** Trigger {

    **case** end

    **indirect** **case** after(TriggerType, \[Status\], Trigger)

}

We can use nested enums to define multiple triggers and construct even more complex attacks.  For our melee attack, let’s say that it will deal one point of damage.   

**let** meleeTrigger: Trigger = .after(.hit, \[.damage(1)\], .end)

Or, we can have it be a poison-coated dagger that can also poison our foes, but only if we dealt damage with it.

**let** meleeTrigger: Trigger = .after(.hit, \[.damage(1)\], .after(.damage, \[.poison\], .end))

With this logic, we can construct any type of effect, and chaining enums lets us mix and match whatever we need.

**ATTACKS**

Ok, so now that we have our effects and targets, we can define a simple list of attacks:

**enum** Attack {

    **case** melee(Target, Trigger)

    **case** spell(String, Target, Trigger)

}

Maybe our heal spell is:

**let** healSpell: Attack = .spell("Heal", .target(.ally, .inRange(4)), .after(.hit, \[.heal(1)\], .end))

Our fire blast attack is:

**let** infernoSpell: Attack = .spell("Inferno", .all(.enemy, .around, .inRange(6)), .after(.hit, \[.damage(3)\], .after(.damage, \[.burn\], .end)))

We can now build on top of this and define enums for our weapons. Adding associated values can make it so that different weapons of the same type have different damage values (such as a wooden spear versus an iron spear):

**enum** Weapon {

    **case** spear(dmg: Int)

    **case** poisonDagger

    

    **var** attack: Attack {

        **switch** **self** {

        **case** **let** .spear(dmg):

            **let** meleeTarget: Target = .target(.enemy, .inRange(2))

            **return** .melee(meleeTarget, .after(.hit, \[.damage(dmg)\], .end))

        **case** .poisonDagger:

            **let** meleeTarget: Target = .target(.enemy, .inRange(1))

            **return** .melee(meleeTarget, .after(.hit, \[.damage(1)\], .after(.damage, \[.poison\], .end)))

        }

    }

}

We can do the same for spells. A magical tome can have a group of spells associated with it. Or we can define a new enum for different enemies in our game. Each enemy can perform different attack actions:

**enum** Enemy {

    **case** goblin

    **case** dragon

    

    **var** actions: \[Attack\] {

        **switch** **self** {

        **case** .goblin:

            **return** \[Weapon.poisonDagger.attack\]

        **case** .dragon:

            **let** bite: Attack = .melee(.target(.enemy, .inRange(1)), .after(.hit, \[.damage(3)\], .after(.kill, \[.heal(1)\], .end)))

            **let** dracarys: Attack = .spell("Inferno", .all(.enemy, .around, .inRange(6)), .after(.hit, \[.damage(3)\], .after(.damage, \[.burn\], .end)))

            **return** \[bite, dracarys\]

        }

    }

}

##### Using Enums to Create an App

Let’s now look into a different, more practical approach for using enums in apps. Say you’re a train enthusiast, and as such, you're creating an app to manage your train emporium. Again, we can use our trusty enums to create our models. Let’s start by creating an enum for the cargo of our trains. They can either hold some sort of material or be empty:

**enum** Cargo {

    **case** chemical(String, Int)

    **case** coal(Int)

    **case** ore(Int)

    **case** lumber(Int)

    **case** none

}

Then, to create our train model, we can do something like this:

**enum** Train {

    **case** tail(id: String, cargo: Cargo)

    **indirect** **case** car(id: String, cargo: Cargo, next: Train)

}

In this case, we can have an ID for each car, the cargo it hauls, and possibly the next car attached. This is simple and elegant. This also means that we can attach one train to another. 

So we can start creating our trains easily:

**let** train: Train = .car(id: "WX900", cargo: .lumber(20), next:

                   .car(id: "WX120", cargo: .ore(40), next:

                   .car(id: "TA763", cargo: .chemical("Radioactive Waste", 20), next:

                   .tail(id: "T800", cargo: .coal(100)))))

Now, if we want to know the total weight of the cargo, we can add a computed property to our enums:

**enum** Cargo {

    **case** chemical(String, Int)

    **case** coal(Int)

    **case** ore(Int)

    **case** lumber(Int)

    **case** none

    

    **var** tons: Int {

        **switch** **self** {

        **case** .chemical(**\_**, **let** tons):

            **return** tons

        **case** .coal(**let** tons), .ore(**let** tons), .lumber(**let** tons):

            **return** tons

        **case** .none:

            **return** 0

        }

    }

}

And a couple more for our train model:

**enum** Train {

    **case** tail(id: String, cargo: Cargo)

    **indirect** **case** car(id: String, cargo: Cargo, next: Train)

    

    **var** numberOfCars: Int {

        **switch** **self** {

        **case** .car(id: **\_**, cargo: **\_**, next: **let** next):

            **return** 1 + next.numberOfCars

        **default**:

            **return** 1

        }

    }

    

    **var** totalTons: Int {

        **switch** **self** {

        **case** .car(id: **\_**, cargo: **let** cargo, next: **let** next):

            **return** cargo.tons + next.totalTons

        **case** .tail(id: **\_**, cargo: **let** cargo):

            **return** cargo.tons

        }

    }

}

So getting those properties becomes something as simple as:

train.numberOfCars *// 4*

train.totalTons *// 180*

##### Conclusion

As you can see, enums are a very powerful type in Swift. They are flexible enough to be used as building blocks for data and simple enough to understand and use. I had never thought of using enums instead of structs and classes, but now I imagine that we might (one day) end up doing enum-oriented programming.

[View full post](https://blog.avenuecode.com/swift-and-the-hidden-power-of-enums)

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Eduardo Salinas"
  },
  "dateModified" : "2019-10-30T17:00:00.849Z",
  "datePublished" : "2019-10-30T17:00:00Z",
  "headline" : "Swift and the Hidden Power of Enums",
  "image" : {
    "@type" : "ImageObject",
    "height" : 3742,
    "url" : "https://info.avenuecode.com/hubfs/esther-jiao-FKZwWLWgGyM-unsplash.jpg",
    "width" : 6000
  },
  "mainEntityOfPage" : "https://blog.avenuecode.com/swift-and-the-hidden-power-of-enums",
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "height" : 60,
      "url" : "/hs/hsstatic/content_shared_assets/static-1.4092/img/default-amp-logo.png",
      "width" : 60
    },
    "name" : "Avenue Code Snippets"
  }
}
```