看例學Rust[三]---自定義類型

Rust is a modern systems programming language focusing on safety and speed. It accomplishes these goals by being memory safe without using garbage collection.
Rust by Example is a collection of examples that illustrate various Rust concepts and the standard libraries. You can also check out the source code for this site.
Be sure to have Rust installed and the docs at hand, and let's start!

在 Rust 中自定義的數據類型主要是通過下面兩個關鍵字:

  • struct: 定義結構體
  • enum: 定義枚舉類型

常量是用conststatic這兩個關鍵字來聲明.

1. 結構體

struct關鍵字能夠定義三種不同的結構體:

  • 最基本的元組結構體,又叫元組(Tupels)
  • 經典的類C結構體
  • 單元結構體(泛結構體?)沒有成員

示例

// A unit struct
// 單元結構體(泛結構體?)
struct Nil;

// A tuple struct
// 元組結構體
struct Pair(i32, f64);

// A struct with two fields
// 擁有兩個成員的結構體
struct 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 分解,同時得到各成員值
    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

2.枚舉

enum關鍵字能夠創建包含不同數據類型的類型.對struct有效的類型同樣對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:
// 用` enum `創建一個"人"的類, 注意,名字和類型信息都是指特定的數據類型:
// `Skinny != Fat` and `Height(i32) != Weight(i32)`. Each
// is different and independent.
//  `Skinny != Fat` and `Height(i32) != Weight(i32)`. 他們是不同的,獨立的.
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.
// 一個需要傳入 `Person`枚舉作為參數,無返回值的函數.
fn inspect(p: Person) {
    // Usage of an `enum` must cover all cases (irrefutable)
    // so a `match` is used to branch over it.
    // 枚舉的使用必須覆蓋所有條目,所以` match `里面有它所有的分支.
    match p {
        Person::Skinny    => println!("Is skinny!"),
        Person::Fat       => println!("Is fat!"),
        // Destructure `i` from inside the `enum`.
        // 從枚舉中分解出 ` i `
        Person::Height(i) => println!("Has a height of {}.", i),
        Person::Weight(i) => println!("Has a weight of {}.", i),
        // Destructure `Info` into `name` and `height`.
        // 分解出` Info ` 到 `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.
    // `to_owned()`創建字符串切片的`String`類型.
    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!

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 `帶上每一個名字
    use Status::{Poor, Rich};
    // Automatically `use` each name inside `Work`.
    // 自動` use `所有名字
    use Work::*;

    // Equivalent to `Status::Poor`.
    // 等價于`Status::Poor`
    let status = Poor;
    // Equivalent to `Work::Civilian`.
    // 等價于`Work::Civilian`
    let work = Civilian;

    match status {
        // Note the lack of scoping because of the explicit `use` above.
        // 注意不需要帶上域(`Status`),因為明確地使用了`use`
        Rich => println!("The rich have lots of money!"),
        Poor => println!("The poor have no money..."),
    }

    match work {
        // Note again the lack of scoping.
        // 同樣不用帶上域(`Work`)
        Civilian => println!("Civilians work!"),
        Soldier  => println!("Soldiers fight!"),
    }
}

結果

The poor have no money...
Civilians work!

2.2. 類C枚舉

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 discriminator
enum 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 0
one is 1
roses are #ff0000
violets are #0000ff

2.3 測試用例:鏈表

枚舉比較常見用來創建鏈表.

示例

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 enum
impl 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: 3
3, 2, 1, Nil
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容