1、定义枚举
枚举允许我们列举所有可能的值来定义一个类型
如: IP地址:lPv4、lPv6
enum IpAddressKind{
V4,
V6
}
定义枚举的时候命名使用CamelCase的命名风格
枚举值
fn main() {
let four = IpAddressKind::V4;
let six = IpAddressKind::V6;
route(four);
route(six);
route(IpAddressKind::V4);
}
#[derive(Debug)]
enum IpAddressKind{
V4,
V6
}
fn route(ip_kind:IpAddressKind) {
println!("{:?}",ip_kind);
}
将数据附加到枚举的变体中
fn main() {
let four = IpAddressKind::V4;
let six = IpAddressKind::V6;
let s1 = IpAddr{
kind:four,
address:String::from("127.0.0.1")
};
let s2 = IpAddr{
kind:six,
address:String::from("::1")
};
}
#[derive(Debug)]
enum IpAddressKind{
V4,
V6
}
struct IpAddr {
kind:IpAddressKind,
address:String
}
上面的代码中我们可以把枚举作为结构体的值,但是枚举的数据可以直接添加到枚举中
enum lpAddr {
v4(String),
v6(String),
}
优点:
不需要额外使用struct
每个变体可以拥有不同的类型以及关联的数据量
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String)
}
我们来看一下例子:
fn main() {
let four = IpAddr::V4(127, 0, 0, 1);
let six = IpAddr::V6(String::from("::1"));
println!("{:?}",four);
println!("{:?}",six);
}
#[derive(Debug)]
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String)
}
标准库中的lpAddr
struct lpv4Addr {}
struct lpv6Addr {}
enum lpAddr {
v4(Ipv4Addr),
v6(Ipv6Addr),
}
我们再来看一下其他例子:
fn main() {
let q = Message::Quit;
let m = Message::Move { x: 12, y: 13 };
let w = Message::Write(String::from("455"));
let c = Message::ChangeColor(127, 255, 0, );
}
#[derive(Debug)]
enum Message {
Quit,
Move{x:i32,y:i32},
Write(String),
ChangeColor(i32,i32,i32)
}
为枚举定义方法
使用impl这个关键字来定义方法
fn main() {
let q = Message::Quit;
let m = Message::Move { x: 12, y: 13 };
let w = Message::Write(String::from("455"));
let c = Message::ChangeColor(127, 255, 0, );
m.call()
}
#[derive(Debug)]
enum Message {
Quit,
Move{x:i32,y:i32},
Write(String),
ChangeColor(i32,i32,i32)
}
impl Message {
fn call(&self) {
}
}
2、Option枚举
定义于标准库中
在Prelude(预导入模块)中
描述了:某个值可能存在(某种类型)或不存在的情况
Rust没有Null。其它语言中:
Null是一个值,它表示“没有值”
一个变量可以处于两种状态:空值(null)、非空
Null引用:Billion Dollar Mistake
Null的问题在于:当你尝试像使用非 Null值那样使用Null值的时候,就会引起某种错误
Null的概念还是有用的:因某种原因而变为无效或缺失的值
Rust中类似 Null概念的枚举- Option<T>
标准库中的定义:
enum option<T> {
Some(T),
None,
}
它包含在 Prelude(预导入模块)中。可直接使用:
- Option<T>
- Some(T)
- None
例如:
fn main() {
let some_number = Some(5);
let some_string = Some("A String");
let absent_number: Option<i32> = None;
}
Option<T>比Null好在哪?
Option<T>和T是不同的类型,不可以把Option<T>直接当成T(例子)
fn main() {
let x:i32 = 5;
let y:Option<i32> = Some(5);
let sum = x + y;
}
上述代码中就会报错,因为i32类型和Option<i32>类型是不一样的,无法进行相加
若想使用Option<T>中的T,必须将它转换为T
而在C#中:
- string a = null;
- - string b = a +“12345";
fn main() {
let x:i32 = 5;
let y:Option<i32> = Some(5);
let sum = x + y.unwrap_or_default();
println!("{}",sum)
}
3、控制流运算符– match
允许一个值与一系列模式进行匹配,并执行匹配的模式对应的代码
模式可以是字面值、变量名、通配符...
fn main() {
let x:i32 = 5;
let y:Option<i32> = Some(5);
let sum = x + y.unwrap_or_default();
println!("{}",sum)
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter
}
fn value_in_cents(coin:Coin)->i8 {
match coin {
Coin::Penny => {
println!("penny");
1
},
Coin::Nickel=> 5,
Coin::Dime=> 15,
Coin::Quarter=> 25,
}
}
绑定值的模式
匹配的分支可以绑定到被匹配对象的部分值。
因此,可以从enum变体中提取值
fn main() {
let c = Coin::Quarter(UsState::Alaska);
println!("{}",value_in_cents(c));
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState)
}
#[derive(Debug)]
enum UsState {
Alabama,
Alaska
}
fn value_in_cents(coin:Coin)->i8 {
match coin {
Coin::Penny => {
println!("penny");
1
},
Coin::Nickel=> 5,
Coin::Dime=> 15,
Coin::Quarter(state)=> {
println!("State quarter from {:?}!",state);
25
},
}
}
匹配Option<T>
fn main() {
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
}
fn plus_one(x:Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i + 1),
}
}
match匹配必须穷举所有的可能
_通配符:替代其余没列出的值
fn main() {
let v = 1u8;
match v {
1 => println!("one"),
3 => println!("three"),
5 => println!("five"),
7 => println!("seven"),
_ => (),
}
}
if let
它是一个简单的控制流表达式
处理只关心一种匹配而忽略其它匹配的情况
fn main() {
let v = Some(3);
match v {
Some(3) => println!("three"),
_ => (),
}
if let Some(3) = v {
println!("three");
}
}
更少的代码,更少的缩进,更少的模板代码。
放弃了穷举的可能
可以把if let看作是match的语法糖
搭配else
fn main() {
let v = Some(2);
match v {
Some(3) => println!("three"),
_ => (),
}
if let Some(3) = v {
println!("three");
} else {
println!("other");
}
}