邊做邊學Rust之使用者自訂類型_Rust

來源:互聯網
上載者:User
3 使用者自訂類型

Rust自訂類型主要通過下面兩個關鍵進行定義: struct:定義一個結構 enum:定義一個枚舉 常量能以通過const和static關鍵字建立。

3.1 結構


有三種類型的結構(“structs”),可以使用struct關鍵字來建立: 元組結構體,又名元組 傳統C結構體 元結構體,無field,為了做成通用類型

// A unit structstruct Nil;// A tuple structstruct Pair(i32, f64);// A struct with two fieldsstruct Point {    x: f64,    y: f64,}// Structs can be reused as fields of another struct#[allow(dead_code)]struct Rectangle {    p1: Point,    p2: Point,}fn main() {    // Instantiate a `Point`    let point: Point = Point { x: 0.3, y: 0.4 };    // Access the fields of the point    println!("point coordinates: ({}, {})", point.x, point.y);    // Destructure the point using a `let` binding    let Point { x: my_x, y: my_y } = point;    let _rectangle = Rectangle {        // struct instantiation is an expression too        p1: Point { x: my_y, y: my_x },        p2: point,    };    // Instantiate a unit struct    let _nil = Nil;    // Instantiate a tuple struct    let pair = Pair(1, 0.1);    // Destructure a tuple struct    let Pair(integer, decimal) = pair;    println!("pair contains {:?} and {:?}", integer, decimal);}

程式執行結果:


point coordinates: (0.3, 0.4)pair contains 1 and 0.1

3.2 枚舉


enum關鍵字允許建立一個可能有許多變體的變數。每一個對結構體來說是合法的變體,對枚舉同樣是合法的。


// An attribute to hide warnings for unused code.#![allow(dead_code)]// Create an `enum` to classify someone. Note how both names// and type information together specify the variant:// `Skinny != Fat` and `Height(i32) != Weight(i32)`. Each// is different and independent.enum Person {    // An `enum` may either be `unit-like`,    Skinny,    Fat,    // like tuple structs,    Height(i32),    Weight(i32),    // or like structures.    Info { name: String, height: i32 }}// A function which takes a `Person` enum as an argument and// returns nothing.fn inspect(p: Person) {    // Usage of an `enum` must cover all cases (irrefutable)    // so a `match` is used to branch over it.    match p {        Person::Skinny    => println!("Is skinny!"),        Person::Fat       => println!("Is fat!"),        // Destructure `i` from inside the `enum`.        Person::Height(i) => println!("Has a height of {}.", i),        Person::Weight(i) => println!("Has a weight of {}.", i),        // Destructure `Info` into `name` and `height`.        Person::Info { name, height } => {            println!("{} is {} tall!", name, height);        },    }}fn main() {    let person = Person::Height(18);    let danny  = Person::Weight(10);    // `to_owned()` creates an owned `String` from a string slice.    let dave   = Person::Info { name: "Dave".to_owned(), height: 72 };    let john   = Person::Fat;    let larry  = Person::Skinny;    inspect(person);    inspect(danny);    inspect(dave);    inspect(john);    inspect(larry);}

程式運行結果:


Has a height of 18.Has a weight of 10.Dave is 72 tall!Is fat!Is skinny!

3.2.1 use

可以使用use聲明,所以不用手動指定範圍:

// An attribute to hide warnings for unused code.#![allow(dead_code)]enum Status {    Rich,    Poor,}enum Work {    Civilian,    Soldier,}fn main() {    // Explicitly `use` each name so they are available without    // manual scoping.    use Status::{Poor, Rich};    // Automatically `use` each name inside `Work`.    use Work::*;    // Equivalent to `Status::Poor`.    let status = Poor;    // Equivalent to `Work::Civilian`.    let work = Civilian;    match status {        // Note the lack of scoping because of the explicit `use` above.        Rich => println!("The rich have lots of money!"),        Poor => println!("The poor have no money..."),    }    match work {        // Note again the lack of scoping.        Civilian => println!("Civilians work!"),        Soldier  => println!("Soldiers fight!"),    }}

程式執行結果:


The poor have no money...Civilians work!

3.2.2 C-like


enum也能像C預言的枚舉那樣使用。


// An attribute to hide warnings for unused code.#![allow(dead_code)]// enum with implicit discriminator (starts at 0)enum Number {    Zero,    One,    Two,}// enum with explicit discriminatorenum Color {    Red = 0xff0000,    Green = 0x00ff00,    Blue = 0x0000ff,}fn main() {    // `enums` can be cast as integers.    println!("zero is {}", Number::Zero as i32);    println!("one is {}", Number::One as i32);    println!("roses are #{:06x}", Color::Red as i32);    println!("violets are #{:06x}", Color::Blue as i32);}

程式運行結果為:


zero is 0one is 1roses are #ff0000violets are #0000ff

3.2.3 測試案例:鏈表


enums一個普通的使用時建立鏈表:


use List::*;enum List {    // Cons: Tuple struct that wraps an element and a pointer to the next node    Cons(u32, Box<List>),    // Nil: A node that signifies the end of the linked list    Nil,}// Methods can be attached to an enumimpl List {    // Create an empty list    fn new() -> List {        // `Nil` has type `List`        Nil    }    // Consume a list, and return the same list with a new element at its front    fn prepend(self, elem: u32) -> List {        // `Cons` also has type List        Cons(elem, Box::new(self))    }    // Return the length of the list    fn len(&self) -> u32 {        // `self` has to be matched, because the behavior of this method        // depends on the variant of `self`        // `self` has type `&List`, and `*self` has type `List`, matching on a        // concrete type `T` is preferred over a match on a reference `&T`        match *self {            // Can't take ownership of the tail, because `self` is borrowed;            // instead take a reference to the tail            Cons(_, ref tail) => 1 + tail.len(),            // Base Case: An empty list has zero length            Nil => 0        }    }    // Return representation of the list as a (heap allocated) string    fn stringify(&self) -> String {        match *self {            Cons(head, ref tail) => {                // `format!` is similar to `print!`, but returns a heap                // allocated string instead of printing to the console                format!("{}, {}", head, tail.stringify())            },            Nil => {                format!("Nil")            },        }    }}fn main() {    // Create an empty linked list    let mut list = List::new();    // Append some elements    list = list.prepend(1);    list = list.prepend(2);    list = list.prepend(3);    // Show the final state of the list    println!("linked list has length: {}", list.len());    println!("{}", list.stringify());}

程式運行結果:


linked list has length: 33, 2, 1, Nil

3.3 常量


Rust有兩種不同類型的常量,這些常量可以在任何作用於定義,包括全域。兩種方法都需要顯示聲明: const:一個不可改變的值(通常用法) static:一個可能在staic聲明周期內可變的變數 “string”是一個特例。它可以直接賦值給一個static變數,而不需要修改,因為它的類型簽名:&'static str已經使用了'static生命週期。所有其他的參考型別必須使用'static聲明走起做特殊註解。

// Globals are declared outside all other scopes.static LANGUAGE: &'static str = "Rust";const  THRESHOLD: i32 = 10;fn is_big(n: i32) -> bool {    // Access constant in some function    n > THRESHOLD}fn main() {    let n = 16;    // Access constant in the main thread    println!("This is {}", LANGUAGE);    println!("The threshold is {}", THRESHOLD);    println!("{} is {}", n, if is_big(n) { "big" } else { "small" });    // Error! Cannot modify a `const`.    //THRESHOLD = 5;    // FIXME ^ Comment out this line}

程式運行結果:


This is RustThe threshold is 1016 is big


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.