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
}
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
}
Structs with no fields
struct AlwaysEqual;
fn main() {
let subject = AlwaysEqual;
}
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
}
#[derive(Debug)] // Required for print of struct
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
println!("rect1 is {:?}", rect1);
dbg!(&rect1);
}
let rect1 = Rectangle {
width: dbg!(30 * scale),
height: 50,
};
dbg!(&rect1); // use ref here to prevent ownership changes
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()
);
}
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);
impl Rectangle {
fn square(size: u32) -> Self {
Self {
width: size,
height: size,
}
}
}
Rectangle::square(3);
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")
}
}