看例學(xué)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 中自定義的數(shù)據(jù)類型主要是通過(guò)下面兩個(gè)關(guān)鍵字:

  • struct: 定義結(jié)構(gòu)體
  • enum: 定義枚舉類型

常量是用conststatic這兩個(gè)關(guān)鍵字來(lái)聲明.

1. 結(jié)構(gòu)體

struct關(guān)鍵字能夠定義三種不同的結(jié)構(gòu)體:

  • 最基本的元組結(jié)構(gòu)體,又叫元組(Tupels)
  • 經(jīng)典的類C結(jié)構(gòu)體
  • 單元結(jié)構(gòu)體(泛結(jié)構(gòu)體?)沒(méi)有成員

示例

// A unit struct
// 單元結(jié)構(gòu)體(泛結(jié)構(gòu)體?)
struct Nil;

// A tuple struct
// 元組結(jié)構(gòu)體
struct Pair(i32, f64);

// A struct with two fields
// 擁有兩個(gè)成員的結(jié)構(gòu)體
struct Point {
    x: f64,
    y: f64,
}

// Structs can be reused as fields of another struct
// 結(jié)構(gòu)體能夠作為其它結(jié)構(gòu)體的成員
#[allow(dead_code)]
struct Rectangle {
    p1: Point,
    p2: Point,
}

fn main() {
    // Instantiate a `Point`
    // 實(shí)例化一個(gè)點(diǎn)
    let point: Point = Point { x: 0.3, y: 0.4 };

    // Access the fields of the point
    // 訪問(wèn)改點(diǎn)的成員
    println!("point coordinates: ({}, {})", point.x, point.y);

    // Destructure the point using a `let` binding
    // 用 let 分解,同時(shí)得到各成員值
    let Point { x: my_x, y: my_y } = point;

    let _rectangle = Rectangle {
        // struct instantiation is an expression too
        // 結(jié)構(gòu)體的實(shí)例化是表達(dá)式,即有返回值
        p1: Point { x: my_y, y: my_x },
        p2: point,
    };

    // Instantiate a unit struct
    // 實(shí)例化一個(gè)單元結(jié)構(gòu)體
    let _nil = Nil;

    // Instantiate a tuple struct
    // 實(shí)例化一個(gè)元組結(jié)構(gòu)體
    let pair = Pair(1, 0.1);

    // Destructure a tuple struct
    // 結(jié)構(gòu)一個(gè)元組結(jié)構(gòu)體
    let Pair(integer, decimal) = pair;

    println!("pair contains {:?} and {:?}", integer, decimal);
}

結(jié)果

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

2.枚舉

enum關(guān)鍵字能夠創(chuàng)建包含不同數(shù)據(jù)類型的類型.對(duì)struct有效的類型同樣對(duì)enum有效.

示例

// An attribute to hide warnings for unused code.
// 對(duì)未使用的代碼忽略警告
#![allow(dead_code)]

// Create an `enum` to classify someone. Note how both names
// and type information together specify the variant:
// 用` enum `創(chuàng)建一個(gè)"人"的類, 注意,名字和類型信息都是指特定的數(shù)據(jù)類型:
// `Skinny != Fat` and `Height(i32) != Weight(i32)`. Each
// is different and independent.
//  `Skinny != Fat` and `Height(i32) != Weight(i32)`. 他們是不同的,獨(dú)立的.
enum Person {
    // An `enum` may either be `unit-like`,
    // 一個(gè)枚舉可以是 單元
    Skinny,
    Fat,
    // like tuple structs,
    // 元組
    Height(i32),
    Weight(i32),
    // or like structures.
    // 結(jié)構(gòu)體
    Info { name: String, height: i32 }
}

// A function which takes a `Person` enum as an argument and
// returns nothing.
// 一個(gè)需要傳入 `Person`枚舉作為參數(shù),無(wú)返回值的函數(shù).
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()`創(chuàng)建字符串切片的`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);
}

結(jié)果

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

2.1 use

use關(guān)鍵字來(lái)代替獲取.

// An attribute to hide warnings for unused code.
// 對(duì)未使用的代碼忽略警告
#![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 `帶上每一個(gè)名字
    use Status::{Poor, Rich};
    // Automatically `use` each name inside `Work`.
    // 自動(dòng)` use `所有名字
    use Work::*;

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

    match status {
        // Note the lack of scoping because of the explicit `use` above.
        // 注意不需要帶上域(`Status`),因?yàn)槊鞔_地使用了`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!"),
    }
}

結(jié)果

The poor have no money...
Civilians work!

2.2. 類C枚舉

enum 同樣可以作為C中的枚舉類型使用.

// An attribute to hide warnings for unused code.
// 對(duì)未使用的代碼忽略警告
#![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);
}

結(jié)果

zero is 0
one is 1
roses are #ff0000
violets are #0000ff

2.3 測(cè)試用例:鏈表

枚舉比較常見(jiàn)用來(lái)創(chuàng)建鏈表.

示例

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());
}

結(jié)果

linked list has length: 3
3, 2, 1, Nil
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末琐驴,一起剝皮案震驚了整個(gè)濱河市秤标,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌牢酵,老刑警劉巖衙猪,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件垫释,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡铁追,警方通過(guò)查閱死者的電腦和手機(jī)茫船,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)涩禀,“玉大人然眼,你說(shuō)我怎么就攤上這事∮炱瘢” “怎么了鲸匿?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵带欢,是天一觀的道長(zhǎng)烤惊。 經(jīng)常有香客問(wèn)我吁朦,道長(zhǎng),這世上最難降的妖魔是什么逗宜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任锦溪,我火速辦了婚禮府怯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘则涯。我一直安慰自己冲簿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布档礁。 她就那樣靜靜地躺著吝沫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪羹幸。 梳的紋絲不亂的頭發(fā)上辫愉,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天恭朗,我揣著相機(jī)與錄音,去河邊找鬼痰腮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蔚出,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播骄酗,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼趋翻,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了师骗?” 一聲冷哼從身側(cè)響起讨惩,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤荐捻,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后处面,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昵济,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年砸紊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了囱挑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡游添,死狀恐怖通熄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情廊酣,我是刑警寧澤赏枚,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布晓猛,位于F島的核電站凡辱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏洪燥。R本人自食惡果不足惜乳乌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一汉操、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧客情,春花似錦癞己、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)愉耙。三九已至,卻和暖如春朴沿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背魏铅。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工坚芜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沧竟。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓屯仗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親魁袜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容