- Enums
Enums
代码语言:javascript复制fn main() {
enum IpAddrKind {
V4,
V6,
}
struct IpAddr {
kind: IpAddrKind,
address: String,
}
let home = IpAddr {
kind: IpAddrKind::V4,
address: String::from("127.0.0.1"),
};
let loopback = IpAddr {
kind: IpAddrKind::V6,
address: String::from("::1"),
};
}
Enums works as Functions
And you can put data directly to the enum values:
代码语言:javascript复制// this snippet is simpler version of the above snippet
fn main() {
enum IpAddr {
V4(String),
V6(String),
}
let home = IpAddr::V4(String::from("127.0.0.1"));
let loopback = IpAddr::V6(String::from("::1"));
}
Enums Vs Structs
There’s another advantage to using an enum rather than a struct: each variant can have different types and amounts of associated data.
代码语言:javascript复制fn main() {
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
}
Store Structs in Enums
Example from Rust std lib:
代码语言:javascript复制#![allow(unused)]
fn main() {
struct Ipv4Addr {
// --snip--
}
struct Ipv6Addr {
// --snip--
}
enum IpAddr {
V4(Ipv4Addr),
V6(Ipv6Addr),
}
}
And another example:
代码语言:javascript复制enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
// above snippet is equivalent to below snippet
struct QuitMessage; // unit struct
struct MoveMessage {
x: i32,
y: i32,
}
struct WriteMessage(String); // tuple struct
struct ChangeColorMessage(i32, i32, i32); // tuple struct
Define Methods on Enums
代码语言:javascript复制fn main() {
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
impl Message {
// add method for Enum `Message`
fn call(&self) {
// method body would be defined here
}
}
let m = Message::Write(String::from("hello"));
m.call();
}
Use Option
Enum instead of null value
代码语言:javascript复制enum Option<T> {
None,
Some(T),
}
Rust does not have null
type, instead use Option
.
Compiler will make sure we handle that case before using the value.
代码语言:javascript复制fn main() {
let x: i8 = 5;
let y: Option<i8> = Some(5);
let sum = x y; // Error: no implementation for `i8 Option<i8>`
}
The match
Control Flow Construct
match
seems very similar to an expression used with if, but there’s a big difference: with if, the expression needs to return a Boolean value, but here, it can return any type. The type of coin in this example is the Coin enum that we defined on the first line.
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
Patterns that Bind to Values
代码语言:javascript复制#[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) => { // Works like a method
// `{:?}` uses debug trait for output
println!("State quarter from {:?}!", state);
25
}
}
}
fn main() {
value_in_cents(Coin::Quarter(UsState::Alaska));
}
Matches must be Exhaustive
Matches must cover every possible cases.
代码语言:javascript复制 fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
// All possible cases must be covered due to Option<T> type
Some(i) => Some(i 1),
None => None,
}
}
Catch-all Patterns (other
)
代码语言:javascript复制let x = 5;
match x {
1 => println!("x is 1"),
2 => println!("x is 2"),
// Catch All
other => println!("x is something else: {}", other),
}
The _
Placeholder
Differences: No Binding for this case.
代码语言:javascript复制let value = 5;
match value {
1 => println!("One"),
2 => println!("Two"),
_ => println!("Other value"),
}
if let
: Shorthand for _
placeholder
代码语言:javascript复制fn main() {
let config_max = Some(3u8);
// Original match pattern
match config_max {
Some(max) => println!("The maximum is configured to be {}", max),
_ => (),
}
/*
Shorthand with `if let`
Format:
if let [arm] = [variable] {
...
} else {
...
}
*/
if let Some(max) = config_max {
println!("The maximum is configured to be {}", max);
}
}