zl程序教程

您现在的位置是:首页 >  其他

当前栏目

Rust - 03 - Structs and Methods

2023-02-19 12:23:05 时间

Rust doesn’t allow us to mark only certain fields as mutable. You can only mark whole struct as mutable or immutable.

For struct field you can use spread operator. But remember that data will be moved to new struct.

fn main() {
  // --snip--

  let user1 = User {
      email: String::from("someone@example.com"),
      username: String::from("someusername123"),
      active: true,
      sign_in_count: 1,
  };

  let user2 = User {
      email: String::from("another@example.com"),
      ..user1
  };

  print!("{}", user1.email); // Works
  print!("{}", user1.username); // Do not work, moved to user2 already
}

Tuple Structs

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

fn main() {
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
}

Unit Structs

Structs with no fields

struct AlwaysEqual;

fn main() {
    let subject = AlwaysEqual;
}

Struct as Function Parameter

struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        area(&rect1)
    );
}

fn area(rectangle: &Rectangle) -> u32 {
    rectangle.width * rectangle.height
}

prints to stdout

#[derive(Debug)]   // Required for print of struct

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!("rect1 is {:?}", rect1);
     dbg!(&rect1);
}

prints to stderr

    let rect1 = Rectangle {
        width: dbg!(30 * scale),
        height: 50,
    };
    dbg!(&rect1);  // use ref here to prevent ownership changes

Method

  • Use impl to add method for a struct
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // define method for Rectangle
    // the `&self` is shorthand for `self: &Self` 
    // the type Self is an alias for the type that the impl block is for.
    fn area(&self) -> u32 {  
        self.width * self.height
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}

Calling method with Automatic Referencing and Dereferencing

In C and C++, two different operators are used for calling methods: you use . if you’re calling a method on the object directly and -> if you’re calling the method on a pointer to the object and need to dereference the pointer first. In other words, if object is a pointer, object->something() is similar to (*object).something().

Rust automatically adds in &, &mut, or * so object matches the signature of the method. In other words, the following are the same:

p1.distance(&p2);
(&p1).distance(&p2);

Constructor in methods

impl Rectangle {
    fn square(size: u32) -> Self {
        Self {
            width: size,
            height: size,
        }
    }
}


Rectangle::square(3);

Multiple impl

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

impl Rectangle {
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}


// Caution: for method without ref on self, use `Rectangle::test()` instead 
impl Rectangle {
    fn test() {
        print!("Test")
    }
}