美文网首页
看例学Rust[三]---自定义类型

看例学Rust[三]---自定义类型

作者: 周筱鲁 | 来源:发表于2016-02-17 08:34 被阅读533次

    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
    

    相关文章

      网友评论

          本文标题:看例学Rust[三]---自定义类型

          本文链接:https://www.haomeiwen.com/subject/nfxocttx.html