Rust入门-11-枚举
枚举
通过列举可能的 成员(variants) 来定义一个类型
定义枚举
eg:IP 地址,目前被广泛使用的两个主要 IP 标准:IPv4(version four)和 IPv6(version six)。
一个 IP 地址要么是 IPv4 的要么是 IPv6 的,而且只能是其中一个。
枚举值只能是枚举中一个成员。
通过定义一个 IpAddrKind
枚举来列出 IP 地址可能的类型是V4
还是 V6
enum IpAddrKind {
V4,
V6,
} //定义后IpAddrKind就是可以使用的自定义数据类型了
枚举值
创建 IpAddrKind
两个不同成员的实例:
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
定义一个函数来获取任何 IpAddrKind
:
fn route(ip_type: IpAddrKind) { }
使用任一成员来调用这个函数:
route(IpAddrKind::V4);
route(IpAddrKind::V6);
即
enum{
V4,
V6
}
int main() {
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
route(IpAddrKind::V4);
route(IpAddrKind::V6);
//还可以
//route(four);
//route(six);
}
fn route(ip_type: IpAddrKind) { }
将数据附加到枚举的变体中
enum IpAddrKind {
V4,
V6,
}
struct IpAddr {
kind: IpAddrKind,
address: String, //address ip地址
}
fn main() {
let home = IpAddr {
kind: IpAddrKind::V4,
address: String::from("127.0.0.1"),
};
let loopback = IpAddr {
kind: IpAddrKind::V6,
address: String::from("::1"),
};
}
Rust可以使用枚举将数据直接放进每一个枚举成员
enum IpAddr {
V4(String), //V4与V6的值的变量是字符串
V6(String),
}
let home = IpAddr::V4(String::from("127.0.0.1"));
let loopback = IpAddr::V6(String::from("::1"));
-
这样就不需要额外的结构体
-
每个枚举成员可以处理不同类型和数量的数据
enum IpAddr {
V4(u8, u8, u8, u8), //IPv4 版本的 IP 地址总是含有四个值在 0 和 255 之间的数字部分
V6(String),
}
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
标准库中的 IpAddr
struct Ipv4Addr {
// --snip--
}
struct Ipv6Addr {
// --snip--
}
enum IpAddr {
V4(Ipv4Addr), //V4与V6为结构体类型
V6(Ipv6Addr),
}
即可以将任意类型数据放入枚举成员
另一个枚举也可以作为枚举成员
enum Message {
Quit, //Quit 没有关联任何数据
Move { x: i32, y: i32 }, //Move 包含一个匿名结构体
Write(String), // Write 包含单独一个 String
ChangeColor(i32, i32, i32), //ChangeColor 包含三个 i32
}
为枚举定义方法
可以使用 impl
定义方法(与结构体类似)
impl Message {
fn call(&self) { //self为借用
// 在这里定义方法体
}
}
let m = Message::Write(String::from("hello"));
m.call();
通过self
获取调用方法的值,当 m.call()
运行时 call
方法中的 self
的值就是m
Rust中不存在Null
在其他语言中,null是一个值,表示"没有值"
一个变量可以处于两种状态:空值、非空值
null的问题在于:当尝试使用非null值那样使用null值时,就会引起某种错误
eg:在C#中
string a=null;
string b=a+"12345";// a 与 b 是两种不同的类型
//编译时可能会发生错误
null可以描述因某种原因变为无效或缺失的值
Option枚举
Option
是标准库定义的另一个枚举,而且是在Prelude(预导入模块)中
option枚举描述一个值要么有值要么没值的情况
Rust拥有一个类似Null概念的枚举Option<T>
//Option<T>在标准库中的定义
enum Option<T> {
Some(T),
None,
}
<T>
语法是一个泛型类型参数
Option<T>
枚举是 prelude (预导入模块)中,不需要将其显式引入作用域,可以直接使用。其成员也可以直接使用,可以不需要 Option::
前缀来直接使用 Some
和 None
。
不过Option<T>
也仍是常规的枚举,Some(T)
和 None
仍是 Option<T>
的成员。
let some_number = Some(5);
let some_string = Some("a string");
let absent_number: Option<i32> = None;
使用None
时需要告诉 Option<T>
是什么类型的,因为编译器只通过None
值无法推断出Some
成员保存的值的类型
Option<T>较Null的好处
Option<T>
和 T
(这里 T
可以是任何类型)是不同的类型,不可以把 Option<T>
直接当成 T
let x: i8 = 5;
let y: Option<i8> = Some(5);
let sum = x + y;
该代码不能编译
该代码尝试将Option<i8>
与i8
相加,但是两者类型不同,不可以相加
那么要想对 Option<T>
进行 T
的运算之前必须将其转换为 T
即在Rust中只要这个值不为 Option<T>
,就可以安全地假设该值不为空
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!