網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
前言
書接上文,本篇博客分享的是Rust 枚舉類與模式匹配 的知識(shí)。作為安全性強(qiáng)的語(yǔ)言,Rust 的枚舉類并不像其他編程語(yǔ)言中的概念那樣簡(jiǎn)單,但依然可以十分簡(jiǎn)單的使用。
1、Rust基本枚舉類語(yǔ)法
枚舉允許我們列舉所有可能的值來定義一個(gè)類型,枚舉中的值也叫變體
1.1、定義枚舉
我們舉一個(gè)例子:
IP地址:IPV4、IPV6
enum IpAddrKind{ V4, V6 }
接收枚舉值
let four=IpAddrKind::V4; let six=IpAddrKind::V6;
枚舉的變體都位于標(biāo)識(shí)符的命名空間下,使用::
進(jìn)行分割
1.2、將數(shù)據(jù)附加到枚舉的變體中
形式如下:
enum IpAddr{ V4(String), V6(String) }
優(yōu)點(diǎn):
- 不需要額外使用
struct
來確定類型 - 每個(gè)變體可以擁有不同的類型以及關(guān)聯(lián)的數(shù)據(jù)量
例如:
#[derive(Debug)] enum IpAddrKind { V4(u8,u8,u8,u8), V6(String) } fn main() { let home=IpAddrKind::V4(127, 0, 0, 1); let loopback=IpAddrKind::V6(String::from("這是IPV6")); println!("{:?}\n{:?}",home,loopback); }
運(yùn)行效果:
-
#[derive(Debug)]
作為Rust提供的調(diào)試庫(kù)是可以直接輸出結(jié)構(gòu)體和枚舉類型的 - 但是注意占位符只能使用
{:?}
- 標(biāo)準(zhǔn)庫(kù)中的IpAddr
struct IpV4Addr{ //--snip-- } struct IpV6Addr{ //--snip-- } enum IpAddr { V4(IpV4Addr), V6(IpV6Addr) }
1.3、變體的多種嵌套方式
enum Message { Quit, Move {x:i32,y:u32}, Write(String), ChangeColor(i32,i32,i32) } fn main() { let q=Message::Quit; let m=Message::Move { x: 6, y: 12 }; let w=Message::Write(String::from("hello_world")); let c=Message::ChangeColor(255, 255, 0); }
在這段代碼中枚舉類變體一共有四種數(shù)據(jù)類型:
- 不帶關(guān)聯(lián)數(shù)據(jù)
Quit
- 匿名結(jié)構(gòu)體
Move
- 字符串類型
Write
- 匿名元組結(jié)構(gòu)體
ChangeColor
1.4、定義枚舉方法
和結(jié)構(gòu)體方法類似,使用impl
關(guān)鍵字:
impl Message{ fn call(&self){} }
這里就不具體實(shí)現(xiàn)了,此時(shí)枚舉的所有變體都可以調(diào)用call
方法,例如q.call();
2、Option枚舉
2.1、引入Option枚舉解決控制問題
-
Option
是 Rust 標(biāo)準(zhǔn)庫(kù)中的枚舉類,這個(gè)類用于填補(bǔ) Rust 不支持null
引用的空白。 - 許多語(yǔ)言支持 null 的存在(C/C++、Java),這樣很方便,但也制造了極大的問題,null 的發(fā)明者也承認(rèn)這一點(diǎn),“一個(gè)方便的想法造成累計(jì) 10 億美元的損失”。
-
null
經(jīng)常在開發(fā)者把一切都當(dāng)作不是 null 的時(shí)候給予程序致命一擊:畢竟只要出現(xiàn)一個(gè)這樣的錯(cuò)誤,程序的運(yùn)行就要徹底終止。 - 為了解決這個(gè)問題,很多語(yǔ)言默認(rèn)不允許 null,但在語(yǔ)言層面支持 null 的出現(xiàn)(常在類型前面用 ? 符號(hào)修飾)。
- Java 默認(rèn)支持 null,但可以通過 @NotNull 注解限制出現(xiàn) null,這是一種應(yīng)付的辦法。
Rust 在語(yǔ)言層面徹底不允許空值 null 的存在,但無奈null 可以高效地解決少量的問題,所以 Rust 引入了 Option 枚舉類:
enum Option<T>{ Some(T), None }
2.2、枚舉類的具體使用
枚舉類包含在預(yù)導(dǎo)入模塊中(Prelude),可直接使用:
let some_number=Some(5); let some_string=Some("a string") let absent:Option<&str>=None;
注意:
- 編譯器無法推斷None是什么類型,所以一定要顯示聲明
- 由于
absent
屬于None的變體,因此是無效數(shù)據(jù),也就是null
3、match控制流運(yùn)算符
- 枚舉的目的是對(duì)某一類事物的分類,分類的目的是為了對(duì)不同的情況進(jìn)行描述。
- 基于這個(gè)原理,往往枚舉類最終都會(huì)被分支結(jié)構(gòu)處理(許多語(yǔ)言中的 switch )。
- switch 語(yǔ)法很經(jīng)典,但在 Rust 中并不支持,很多語(yǔ)言摒棄 switch 的原因都是因?yàn)?switch 容易存在因忘記添加 break 而產(chǎn)生的串接運(yùn)行問題,Java 和 C# 這類語(yǔ)言通過安全檢查杜絕這種情況出現(xiàn)。
Rust 通過 match 語(yǔ)句來實(shí)現(xiàn)分支結(jié)構(gòu)。先認(rèn)識(shí)一下如何用 match 處理枚舉類:
fn main() { enum Book { Papery {index: u32}, Electronic {url: String}, } let book = Book::Papery{index: 1001}; let ebook = Book::Electronic{url: String::from("url...")}; match book { Book::Papery { index } => { println!("Papery book {}", index); }, Book::Electronic { url } => { println!("E-book {}", url); } } } //運(yùn)行結(jié)果:Papery book 1001
這是由于book
屬于Papery
的變體,因此會(huì)執(zhí)行第一個(gè)打印語(yǔ)句
match 塊也可以當(dāng)作函數(shù)表達(dá)式來對(duì)待,它也是可以有返回值的:
match 枚舉類實(shí)例 { 分類1 => 返回值表達(dá)式, 分類2 => 返回值表達(dá)式, ... }
但是要謹(jǐn)記:所有返回值表達(dá)式的類型必須一樣!
如果把枚舉類附加屬性定義成元組,在 match 塊中需要臨時(shí)指定一個(gè)名字:
enum Book { Papery(u32), Electronic {url: String}, } let book = Book::Papery(1001); match book { Book::Papery(i) => { println!("{}", i); }, Book::Electronic { url } => { println!("{}", url); } }
變體Papery指定了i
變量,Electronic指定了url
match 除了能夠?qū)γ杜e類進(jìn)行分支選擇以外,還可以對(duì)整數(shù)、浮點(diǎn)數(shù)、字符和字符串切片引用(&str)類型的數(shù)據(jù)進(jìn)行分支選擇。其中,浮點(diǎn)數(shù)類型被分支選擇雖然合法,但不推薦這樣使用,因?yàn)榫葐栴}可能會(huì)導(dǎo)致分支錯(cuò)誤。
對(duì)非枚舉類進(jìn)行分支選擇時(shí)必須注意處理例外情況,即使在例外情況下沒有任何要做的事。例外情況用下劃線 _ 表示:
fn main() { let t = "abc"; match t { "abc" => println!("Yes"), _ => {}, } }
4、if let 語(yǔ)法
通過一個(gè)簡(jiǎn)單的流程控制代碼理解此部分知識(shí):
let i = 0; match i { 0 => println!("zero"), _ => {}, } //主函數(shù)中運(yùn)行結(jié)果:zero
這段程序的目的是判斷 i 是否是數(shù)字 0,如果是就打印 zero。
那么現(xiàn)在用 if let 語(yǔ)法縮短這段代碼:
let i = 0; if let 0 = i { println!("zero"); }
if let 語(yǔ)法格式如下:
if let 匹配值 = 源變量 { 語(yǔ)句塊 }
- 可以在之后添加一個(gè)
else
塊來處理例外情況。
if let 語(yǔ)法可以認(rèn)為是只區(qū)分兩種情況的 match 語(yǔ)句的"語(yǔ)法糖"
在枚舉類中的使用:
fn main() { enum Book { Papery(u32), Electronic(String) } let book = Book::Electronic(String::from("url")); if let Book::Papery(index) = book { println!("Papery {}", index); } else { println!("Not papery book"); } } //運(yùn)行結(jié)果:Not papery book
Rust 枚舉類和模式匹配的知識(shí)就分享到這里了,期待你的鼓勵(lì),這將是我創(chuàng)作的不竭動(dòng)力!
原文鏈接:https://blog.csdn.net/m0_58618795/article/details/126753388
相關(guān)推薦
- 2023-08-16 map()函數(shù)新數(shù)組不能遍歷
- 2023-04-12 python字符串大小寫轉(zhuǎn)換的三種方法_python
- 2022-12-10 C++?vector與數(shù)組轉(zhuǎn)換寫入/讀出文件方式_C 語(yǔ)言
- 2022-10-21 解決Git?Revert?再次合代碼無效問題_相關(guān)技巧
- 2023-01-10 Oracle數(shù)據(jù)庫(kù)如何獲取當(dāng)前自然周,當(dāng)前周的起始和結(jié)束日期_oracle
- 2022-10-16 python3里gbk編碼的問題解決_python
- 2022-03-03 解決Typescript報(bào)錯(cuò):Property 'style' does not exist on
- 2022-05-02 深入了解Python?中線程和進(jìn)程區(qū)別_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支