Associated values

You will use associated values similar to how you used raw values. As in the case of raw values, you can assign enumeration cases a value of a particular type, such as Int. In both instances, an enumeration case has an integer tagging along with it.

While associated values are similar to raw values, here are the unique qualities of associated values:

  1. Each enumeration case has zero or more associated values.
  2. The associated values for each enumeration case have their own data type.
  3. You define associated values with names like you would for named function parameters.

An enumeration can have raw values or associated values, but not both.

In the last mini-exercise, you defined a coin purse. Let’s say you took your money to the bank and deposited it. You could then go to an ATM and withdraw your money:

var balance = 100

func withdraw(amount: Int) { balance -= amount

}

The ATM will never let you withdraw more than you put in, so it needs a way to let you know whether the transaction was successful. You can implement this as an enumeration with associated values:

enum WithdrawalResult {

case success(newBalance: Int) case error(message: String)

}

Each case has a required value to go along with it. For the success case, the associated Int will hold the new balance; for the error case, the associated String will have some kind of error message.

Then you can rewrite the withdraw function to use the enumeration cases:

func withdraw(amount: Int) -> WithdrawalResult { if amount <= balance {

balance -= amount

return .success(newBalance: balance)

} else {

return .error(message: "Not enough money!")

}

}

Now you can perform a withdrawal and handle the result:

let result = withdraw(amount: 99)

switch result {

case .success(let newBalance):

print("Your new balance is: (newBalance)") case .error(let message):

print(message)

}

Notice how you used let bindings to read the associated values. Associated values aren’t properties you can access freely, so you’ll need bindings like these to read them. Remember that the newly bound constants newBalance and message are local to the switch cases. They aren’t required to have the same name as the associated values, although it’s common practice to do so.

You’ll see "Your new balance is:" printed out in the debug console.

Many real-world contexts function by accessing associated values in an enumeration. For example, internet servers often use enumerations to differentiate between types of requests:

enum HTTPMethod { case get

case post(body: String)

}

In the bank account example, you had multiple values you wanted to check for in the enumeration. In places where you only have one, you could instead use pattern matching in an if case or guard case statement. Here’s how that works:

let request = HTTPMethod.post(body: "Hi there") guard case .post(let body) = request else {

fatalError("No message was posted")

}

print(body)

In this code, guard case checks to see if request contains the post enumeration case and if so, reads and binds the associated value.

You’ll also see enumerations used in error handling. The bank account example had

multiple values, but just one generic error case with an associated string. In Chapter 22, “Error Handling” you’ll see how to set up an enumeration with multiple cases to cover individual error conditions.

results matching ""

    No results matching ""