An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code.

###### Types of Enumeration:
• Basic Enumerations
• Enumerations with Raw Values
• Enumerations with Associated Values

## 1. Basic Enumerations

#### 1.1 Create an enumerations

• To create an enumerations, use `enum` keyword and place their entire definition within a pair of braces:
``````enum SomeEnumeration {
// enumeration definition goes here
}
``````
• Here’s an `enum` called Direction. It contains 4 cases. The values defined in an enumeration (such as up, down, left, and right) are its enumeration cases. You use the `case` keyword to introduce new enumeration cases.
``````enum Direction {
case up
case down
case left
case right
}
``````
• Multiple cases can appear on a single line, separated by commas:
``````enum Direction {
case up, down, left, right
}
``````

#### 1.2 Initialization

• Enum values can be used by their fully-qualified name, but you can omit the type name when it can be inferred:
``````var direction = Direction.up
``````
• The type of `direction` is inferred when it is initialized with one of the possible values of `Direction`. Now we can set it to a different `Direction` value using a shorter dot syntax:
``````direction = .down
``````

#### 1.3 Matching Enumeration Values with a Switch Statement

• The most fundamental way of comparing/extracting enum values is with a `switch` statement:
``````direction = .left
switch direction {
case .up:
print("up")
case .down:
print("down")
case .left:
print("left")
case .right:
print("right")
}

//prints "left"
``````

## 2. Enumerations with Raw Values

• An enumeration may contain value. Swift supports the following types for the value of an enum: `Int`, `Float`, `String` and `Bool`.

#### 2.1 Implicitly Assigned Raw Values

• When you’re working with enumerations that store integer or string raw values, you don’t have to explicitly assign a raw value for each case. When you don’t, Swift will automatically assign the values for you.

• The enumeration below is a refinement of the earlier Direction enumeration, with string raw values to represent each direction’s name:

``````enum Direction: String {
case up
case down
case left
case right
}
``````
• In the example above, Direction.up has an implicit raw value of "up", and so on. You access the raw value of an enumeration case with its rawValue property:
``````let direction = Direction.right.rawValue
// direction is "right"
``````
• The enumeration below is a Planet enumeration, with integer raw values to represent each planet’s order from the sun:
``````enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
``````
• In the example above, `Planet.mercury` has an explicit raw value of 1, `Planet.venus` has an implicit raw value of 2, and so on. You access the raw value of an enumeration case with its rawValue property:
``````let earthsOrder = Planet.earth.rawValue
// earthsOrder is 3
``````

#### 2.2 Initializing from a Raw Value

• You may create an enum object using a raw value. it may fail. Therefore, the returned object may be nil. This example identifies earth from its raw value of 3:
``````let possiblePlanet = Planet(rawValue: 3)
// possiblePlanet is of type Planet? and equals Planet.earth
``````
• If you try to find a planet with a position of 11, the optional `Planet` value returned by the raw value initializer will be `nil`:
``````let positionToFind = 11
if let somePlanet = Planet(rawValue: positionToFind) {
switch somePlanet {
case .earth:
print("Mostly harmless")
default:
print("Not a safe place for humans")
}
} else {
print("There isn't a planet at position \(positionToFind)")
}
// Prints "There isn't a planet at position 11"
``````

## 3. Enumerations with Associated Values

• With associated values, each case may contain value along with it. Enum cases can contain one or more associated values.

#### 3.1 Create an Enumerations with Associated Values

• The enumeration below contains the `move` case with an associated distance
``````enum Action {
case jump
case kick
case move(distance: Float)
}
``````

#### 3.2 Matching Enumeration Values with a Switch Statement

• The switch statement can extract the associated value:
``````switch action {
case .jump:
print("Jump")
case .kick:
print("Kick")
case .move(let distance):  // or case let .move(distance):
print("Moving: \(distance)")
}
``````

#### 3.3 Matching Enumeration Values with a if Statement

• A single case extraction can be done using if case:
``````if case .move(let distance) = action {
print("Moving: \(distance)")
}
``````

#### 3.4 Make Equatable Enums with Associated Values

• Enums with associated values are not Equatable by default. Implementation of the `==` operator must be done manually:
``````extension Action: Equatable { }

func ==(lhs: Action, rhs: Action) -> Bool {
switch lhs {
case .jump: if case .jump = rhs { return true }
case .kick: if case .kick = rhs { return true }
case .move(let lhsDistance): if case .move (let rhsDistance) = rhs { return lhsDistance == rhsDistance }
}
return false
}
``````
• Use of `==` operator
``````if Action.move(distance: 10.2) == action {
print("Moving Same Distance")
} else {
print("Moving Different Distance")
}
``````