Rust - 03 - Structs and Methods

2023-01-05 15:57:05 浏览数 (1)

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.

代码语言:javascript复制
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

代码语言:javascript复制
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

代码语言:javascript复制
struct AlwaysEqual;

fn main() {
    let subject = AlwaysEqual;
}

Struct as Function Parameter

代码语言:javascript复制
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
}

Print Debug Info for Struct

prints to stdout

代码语言:javascript复制
#[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

代码语言:javascript复制
    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
代码语言:javascript复制
#[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:

代码语言:javascript复制
p1.distance(&p2);
(&p1).distance(&p2);

Constructor in methods

代码语言:javascript复制
impl Rectangle {
    fn square(size: u32) -> Self {
        Self {
            width: size,
            height: size,
        }
    }
}


Rectangle::square(3);

Multiple impl

代码语言:javascript复制
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")
    }
}

0 人点赞