官术网_书友最值得收藏!

2.3 復(fù)合數(shù)據(jù)類型

復(fù)合數(shù)據(jù)類型是由其他類型組合而成的類型。Rust的復(fù)合數(shù)據(jù)類型有元組、數(shù)組、結(jié)構(gòu)體、枚舉等。

2.3.1 元組類型

元組類型是由一個(gè)或多個(gè)類型的元素組合成的復(fù)合類型,使用小括號(hào)“()”把所有元素放在一起。元素之間使用逗號(hào)“,”分隔。元組中的每個(gè)元素都有各自的類型,且這些元素的類型可以不同。元組的長(zhǎng)度固定,一旦定義就不能再增長(zhǎng)或縮短。如果顯式指定了元組的數(shù)據(jù)類型,那么元素的個(gè)數(shù)必須和數(shù)據(jù)類型的個(gè)數(shù)相同。

我們可以使用“元組名.索引”來訪問元組中相應(yīng)索引位置的元素,元素的索引從0開始計(jì)數(shù)。

代碼清單2-5中,第2行代碼聲明的元組tup1包含3個(gè)元素,類型依次是i8類型、f32類型、bool類型。第3行代碼聲明的元組tup2包含兩個(gè)元素,第1個(gè)元素是f64類型;第2個(gè)元素是元組類型,其中又包含兩個(gè)元素,分別是bool類型和i32類型。第4行代碼聲明的元組tup3只包含一個(gè)元素。當(dāng)元組中只包含一個(gè)元素時(shí),應(yīng)該在元素后面添加逗號(hào)來區(qū)分是元組,而不是括號(hào)表達(dá)式。第6、7行代碼使用“元組名.索引”來訪問元組中相應(yīng)索引位置的元素。第9行代碼使用模式匹配的方式來解構(gòu)賦值,元組中的每個(gè)元素按照位置順序賦值給變量,即tup1的3個(gè)元素分別解構(gòu)賦值給變量x、y和z。

代碼清單2-5 元組類型

 1  fn main() {
 2      let tup1: (i8, f32, bool) = (-10, 7.7, false);
 3      let tup2 = (7.7, (false, 10));
 4      let tup3 = (100, );
 5    
 6      println!("{}, {}", tup1.0, (tup2.1).1);
 7      println!("{}", tup3.0);
 8    
 9      let (x, y, z) = tup1;
10      println!("x: {}, y: {}, z: {}", x, y, z);
11  }
12
13  // -10, 10
14  // 100
15  // x: -10, y: 7.7, z: false

2.3.2 數(shù)組類型

數(shù)組類型是由相同類型的元素組合成的復(fù)合類型,我們可以使用[T; n]表示,T代表元素類型,n代表長(zhǎng)度即元素個(gè)數(shù)。

數(shù)組的聲明和初始化有以下3種方式。

1)指定數(shù)組類型,為每個(gè)元素賦初始值。所有初始值放入中括號(hào)“[]”中,之間使用逗號(hào)“,”分隔。

let arr: [i32; 5] = [1, 2, 3, 4, 5];

2)省略數(shù)組類型,為每個(gè)元素賦初始值。由于已指定每個(gè)元素的初始值,可以從初始值推斷出數(shù)組類型。

let arr = [1, 2, 3, 4, 5];

3)省略數(shù)組類型,為所有元素使用默認(rèn)值初始化。

let arr = [1; 5]; // 等價(jià)于:let arr = [1, 1, 1, 1, 1];

可以使用“數(shù)組名[索引]”來訪問數(shù)組中相應(yīng)索引位置的元素,元素的索引從0開始計(jì)數(shù)。

代碼清單2-6中,第2行代碼聲明的數(shù)組arr1包含5個(gè)i32類型的元素并為每個(gè)元素賦初始值。第3行代碼聲明的數(shù)組arr2省略了數(shù)組類型,由編譯器根據(jù)初始值自動(dòng)推斷數(shù)組類型。第4、5行代碼使用默認(rèn)值初始化數(shù)組,為每個(gè)元素指定初始值為1。

訪問數(shù)組元素時(shí)最常遇到的問題是索引越界,第11行代碼如果訪問arr1[5],將會(huì)拋出index out of bounds: the len is 5 but the index is 5的錯(cuò)誤提示。在實(shí)際項(xiàng)目開發(fā)中,建議使用更加靈活的動(dòng)態(tài)數(shù)組Vec。Vec是允許增長(zhǎng)和縮短長(zhǎng)度的容器類型,其提供的get方法在訪問元素時(shí)可以有效避免索引越界問題。

代碼清單2-6 數(shù)組類型

 1  fn main() {
 2      let arr1: [i32; 5] = [1, 2, 3, 4, 5];
 3      let arr2 = [1, 2, 3, 4, 5];
 4      let arr3: [i32; 5] = [1; 5];
 5      let arr4 = [1; 5];
 6
 7      println!("{:?}", arr1);
 8      println!("{:?}", arr2);
 9      println!("{:?}", arr3);
10      println!("{:?}", arr4);
11      println!("arr1[0]: {}, arr3[2]: {}", arr1[0], arr3[2]);
12  }
13
14  // [1, 2, 3, 4, 5]
15  // [1, 2, 3, 4, 5]
16  // [1, 1, 1, 1, 1]
17  // [1, 1, 1, 1, 1]
18  // arr1[0]: 1, arr3[2]: 1

2.3.3 結(jié)構(gòu)體類型

結(jié)構(gòu)體類型是一個(gè)自定義數(shù)據(jù)類型,通過struct關(guān)鍵字加自定義命名,可以把多個(gè)類型組合在一起成為新的類型。結(jié)構(gòu)體中以“name: type”格式定義字段,name是字段名稱,type是字段類型。結(jié)構(gòu)體名和字段名都遵循變量的命名規(guī)則,結(jié)構(gòu)體名應(yīng)該能夠描述它所組合的數(shù)據(jù)的意義;字段默認(rèn)不可變,并要求明確指定數(shù)據(jù)類型,不能使用自動(dòng)類型推導(dǎo)功能。每個(gè)字段之間用逗號(hào)分隔,最后一個(gè)逗號(hào)可以省略。

結(jié)構(gòu)體類型定義的語法如下。結(jié)構(gòu)體ListNode是鏈表的數(shù)據(jù)結(jié)構(gòu),其中字段next的類型是一個(gè)指向ListNode結(jié)構(gòu)體本身的智能指針。

1  struct ListNode {
2      val: i32,
3      next: Option<Box<ListNode>>,
4  }

代碼清單2-7中,第1~4行代碼定義的結(jié)構(gòu)體Student包含&'static str類型的字段name和i32類型的字段score。第10~13行代碼創(chuàng)建Student的實(shí)例student,以name: value格式為每個(gè)字段進(jìn)行賦值,name是字段名,value是字段的值。第11行代碼是字段初始化簡(jiǎn)寫語法,將變量score的值賦值給字段score,兩者有著相同的名稱,可以簡(jiǎn)寫成score,不用寫成score: score。此外,實(shí)例中字段的順序可以和結(jié)構(gòu)體中聲明的順序不一致。

第15、16行代碼使用“實(shí)例名.字段名”形式更改和訪問結(jié)構(gòu)體實(shí)例某個(gè)字段的值。需要注意的是,結(jié)構(gòu)體實(shí)例默認(rèn)是不可變的,且不允許只將某個(gè)字段標(biāo)記為可變,如果要修改結(jié)構(gòu)體實(shí)例必須在實(shí)例創(chuàng)建時(shí)就聲明其為可變的。

第18~21行代碼創(chuàng)建的實(shí)例student2,除字段name外,其余字段的值與student對(duì)應(yīng)字段的值相同。這就可以使用結(jié)構(gòu)體更新語法,對(duì)除字段name外未顯式設(shè)置值的字段以student實(shí)例對(duì)應(yīng)字段的值來賦值。

代碼清單2-7 結(jié)構(gòu)體類型

 1  struct Student {
 2      name: &'static str,
 3      score: i32,
 4  }
 5  
 6  fn main() {
 7      let score = 59;
 8      let username = "zhangsan";
 9
10      let mut student = Student {
11          score,
12          name: username,
13      };
14
15      student.score = 60;
16      println!("name: {}, score: {}", student.name, student.score);
17
18      let student2 = Student {
19          name: "lisi",
20          ..student
21      };
22
23      println!("name: {}, score: {}", student2.name, student2.score);
24  }
25
26  // name: zhangsan, score: 60
27  // name: lisi, score: 60

另外,還有兩種特殊的結(jié)構(gòu)體:元組結(jié)構(gòu)體和單元結(jié)構(gòu)體。

元組結(jié)構(gòu)體的特點(diǎn)是字段只有類型,沒有名稱。元組結(jié)構(gòu)體的定義以及實(shí)例創(chuàng)建如下所示。

1  struct Color(i32, i32, i32);
2  let black = Color(0, 0, 0);

單元結(jié)構(gòu)體是指沒有任何字段的結(jié)構(gòu)體,代碼如下所示,一般只用于特定的場(chǎng)景,在此不再細(xì)述。

struct Solution;

2.3.4 枚舉類型

枚舉類型是一個(gè)自定義數(shù)據(jù)類型,通過enum關(guān)鍵字加自定義命名來定義。其包含若干枚舉值,可以使用“枚舉名::枚舉值”訪問枚舉值。當(dāng)一個(gè)變量有幾種可能的取值時(shí),我們就可以將它定義為枚舉類型。變量的值限于枚舉值范圍內(nèi),這樣能有效防止用戶提供無效值。根據(jù)枚舉值是否帶有類型參數(shù),枚舉類型還可以分成無參數(shù)枚舉類型和帶參數(shù)枚舉類型。

代碼清單2-8中,第2~6行代碼定義了枚舉類型ColorNoParam,包含Red、Yellow、Blue這3個(gè)枚舉值。第9行代碼聲明的變量color_no_param與枚舉值Red綁定。第10~14行代碼使用match模式匹配來枚舉所有的值,以處理不同值所對(duì)應(yīng)的情況。第1行代碼使用#[derive(Debug)]讓ColorNoParam自動(dòng)實(shí)現(xiàn)Debug trait,只有實(shí)現(xiàn)了Debug trait的類型才擁有使用{:?}格式化打印的行為,具體trait的相關(guān)知識(shí)會(huì)在第5章介紹。

代碼清單2-8 無參數(shù)枚舉類型

 1  #[derive(Debug)]
 2  enum ColorNoParam {
 3      Red,
 4      Yellow,
 5      Blue,
 6  }
 7
 8  fn main() {
 9      let color_no_param = ColorNoParam::Red;
10      match color_no_param {
11          ColorNoParam::Red => println!("{:?}", ColorNoParam::Red),
12          ColorNoParam::Yellow => println!("{:?}", ColorNoParam::Yellow),
13          ColorNoParam::Blue => println!("{:?}", ColorNoParam::Blue),
14      }
15  }
16
17  // Red

代碼清單2-9中,枚舉類型ColorParam的枚舉值都帶有String類型參數(shù),類似于函數(shù)調(diào)用,使用這種枚舉值需要傳入實(shí)參。

代碼清單2-9 帶參數(shù)枚舉類型

 1  #[derive(Debug)]
 2  enum ColorParam {
 3      Red(String),
 4      Yellow(String),
 5      Blue(String),
 6  }
 7
 8  fn main() {
 9      println!("{:?}", ColorParam::Blue(String::from("blue")));
10  }
11
12  // Blue("blue")
主站蜘蛛池模板: 健康| 峨眉山市| 新田县| 玛沁县| 西盟| 蛟河市| 孟州市| 开平市| 青川县| 兖州市| 百色市| 祁连县| 小金县| 钟祥市| 沽源县| 昌平区| 蒙山县| 呼和浩特市| 达州市| 越西县| 兴化市| 贡嘎县| 奉化市| 旬阳县| 方城县| 侯马市| 加查县| 宁武县| 景洪市| 兴宁市| 乐亭县| 商水县| 广河县| 双江| 蒙阴县| 普格县| 隆德县| 松滋市| 克拉玛依市| 鹤山市| 咸宁市|