• 结构体与枚举
    • 结构体
    • 枚举

    结构体与枚举

    结构体

    结构体 (struct) 是一种记录类型,所包含的每个域 (field) 都有一个名称。
    每个结构体也都有一个名称,通常以大写字母开头,使用驼峰命名法。
    元组结构体 (tuple struct) 是由元组和结构体混合构成,元组结构体有名称,
    但是它的域没有。当元组结构体只有一个域时,称为新类型 (newtype)。
    没有任何域的结构体,称为类单元结构体 (unit-like struct)。
    结构体中的值默认是不可变的,需要给结构体加上mut使其可变。

    1. // structs
    2. struct Point {
    3. x: i32,
    4. y: i32,
    5. }
    6. let point = Point { x: 0, y: 0 };
    7. // tuple structs
    8. struct Color(u8, u8, u8);
    9. let android_green = Color(0xa4, 0xc6, 0x39);
    10. let Color(red, green, blue) = android_green;
    11. // A tuple struct’s constructors can be used as functions.
    12. struct Digit(i32);
    13. let v = vec![0, 1, 2];
    14. let d: Vec<Digit> = v.into_iter().map(Digit).collect();
    15. // newtype: a tuple struct with only one element
    16. struct Inches(i32);
    17. let length = Inches(10);
    18. let Inches(integer_length) = length;
    19. // unit-like structs
    20. struct EmptyStruct;
    21. let empty = EmptyStruct;

    一个包含..struct可以用来从其它结构体拷贝一些值或者在解构时忽略一些域:

    1. #[derive(Default)]
    2. struct Point3d {
    3. x: i32,
    4. y: i32,
    5. z: i32,
    6. }
    7. let origin = Point3d::default();
    8. let point = Point3d { y: 1, ..origin };
    9. let Point3d { x: x0, y: y0, .. } = point;

    需要注意,Rust在语言级别不支持域可变性 (field mutability),所以不能这么写:

    1. struct Point {
    2. mut x: i32,
    3. y: i32,
    4. }

    这是因为可变性是绑定的一个属性,而不是结构体自身的。可以使用Cell<T>来模拟:

    1. use std::cell::Cell;
    2. struct Point {
    3. x: i32,
    4. y: Cell<i32>,
    5. }
    6. let point = Point { x: 5, y: Cell::new(6) };
    7. point.y.set(7);

    此外,结构体的域对其所在模块 (mod) 之外默认是私有的,可以使用pub关键字将其设置成公开。

    1. mod graph {
    2. #[derive(Default)]
    3. pub struct Point {
    4. pub x: i32,
    5. y: i32,
    6. }
    7. pub fn inside_fn() {
    8. let p = Point {x:1, y:2};
    9. println!("{}, {}", p.x, p.y);
    10. }
    11. }
    12. fn outside_fn() {
    13. let p = graph::Point::default();
    14. println!("{}", p.x);
    15. // println!("{}", p.y);
    16. // field `y` of struct `graph::Point` is private
    17. }

    枚举

    Rust有一个集合类型,称为枚举 (enum),代表一系列子数据类型的集合。
    其中子数据结构可以为空-如果全部子数据结构都是空的,就等价于C语言中的enum。
    我们需要使用::来获得每个元素的名称。

    1. // enums
    2. enum Message {
    3. Quit,
    4. ChangeColor(i32, i32, i32),
    5. Move { x: i32, y: i32 },
    6. Write(String),
    7. }
    8. let x: Message = Message::Move { x: 3, y: 4 };

    与结构体一样,枚举中的元素默认不能使用关系运算符进行比较 (如==, !=, >=),
    也不支持像+*这样的双目运算符,需要自己实现,或者使用match进行匹配。

    枚举默认也是私有的,如果使用pub使其变为公有,则它的元素也都是默认公有的。
    这一点是与结构体不同的:即使结构体是公有的,它的域仍然是默认私有的。这里的共有/私有仍然
    是针对其定义所在的模块之外。此外,枚举和结构体也可以是递归的 (recursive)。