enum IpAddrKind {
V4,
V6,
}
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
fn route(ip_kind: IpAddrKind) {}
Enum variants can also accept data, and they don’t need to have the same signature:
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
This data can then be used when matching on an enum, see notes below.
Enums can also have associated functions, in exactly the same way a Struct can:
impl Message {
fn call(&self) {
// method body would be defined here
}
}
let m = Message::Write(String::from("hello"));
m.call();
A common and powerful pattern is using Enums in a match block. If the Enum takes data when instantiated, you can extract this data from within the match :
#[derive(Debug)]
enum UsState {
Alabama,
Alaska,
// --snip--
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter(state) => {
println!("State quarter from {state:?}!");
25
}
}
}
In the above example, Quarter takes some data, and the match block destructures that data in the arm that matches Quarters.
if letIf you only care about one of the potential variants of an enum, instead of writing a match expression with the pattern you want and a default, you can use if let
Let’s say you only care about about Wins below:
enum Outcome {
Win(victory_speech: String)
Loss
Draw
}
fn share_victory_speech(outcome: Outcome) {
if let Outcome::Win(msg) = coin {
println!("Here is the victory speech: {msg:?}!");
}
}
You can also have an else:
fn share_victory_speech(outcome: Outcome) {
if let Outcome::Win(msg) = coin {
println!("Here is the victory speech: {msg:?}!");
} else {
println!("They lost!")
}
}