Veamos un ejemplo de metodos:
#[derive(Debug)]
struct Race {
name: String,
laps: Vec<i32>,
}
impl Race {
fn new(name: &str) -> Race { // No receiver, a static method
Race { name: String::from(name), laps: Vec::new() }
}
fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write access to self
self.laps.push(lap);
}
fn print_laps(&self) { // Shared and read-only borrowed access to self
println!("Recorded {} laps for {}:", self.laps.len(), self.name);
for (idx, lap) in self.laps.iter().enumerate() {
println!("Lap {idx}: {lap} sec");
}
}
fn finish(self) { // Exclusive ownership of self
let total = self.laps.iter().sum::<i32>();
println!("Race {} is finished, total lap time: {}", self.name, total);
}
}
fn main() {
let mut race = Race::new("Monaco Grand Prix");
race.add_lap(70);
race.add_lap(68);
race.print_laps();
race.add_lap(71);
race.print_laps();
race.finish();
// race.add_lap(42);
}
Lo ejecutamos :
cargo run
Compiling hello_cargo v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 0.62s
Running `target/debug/hello_cargo`
Recorded 2 laps for Monaco Grand Prix:
Lap 0: 70 sec
Lap 1: 68 sec
Recorded 3 laps for Monaco Grand Prix:
Lap 0: 70 sec
Lap 1: 68 sec
Lap 2: 71 sec
Race Monaco Grand Prix is finished, total lap time: 209
Los cuatro métodos aquí utilizan un receptor de método diferente.
Si intentamos llamar a finalizar dos veces o descomentamos // race.add_lap(42); , lanza este error :
cargo run
Compiling hello_cargo v0.1.0
error[E0382]: borrow of moved value: `race`
--> src/main.rs:37:5
|
30 | let mut race = Race::new("Monaco Grand Prix");
| -------- move occurs because `race` has type `Race`, which does not implement the `Copy` trait
...
36 | race.finish();
| -------- `race` moved due to this method call
37 | race.add_lap(42);
| ^^^^^^^^^^^^^^^^ value borrowed here after move
|
note: this function takes ownership of the receiver `self`, which moves `race`
--> src/main.rs:23:15
|
23 | fn finish(self) { // Exclusive ownership of self
| ^^^^
For more information about this error, try `rustc --explain E0382`.
error: could not compile `hello_cargo` due to previous error
Y es porque finish toma todo el control del registro.
Tenga en cuenta que, aunque los receptores de métodos son diferentes, las funciones no estáticas se denominan de la misma manera en el cuerpo principal. Rust permite la referencia y desreferenciación automática al llamar a métodos. Rust agrega automáticamente los cambios &, *, para que ese objeto coincida con la firma del método.