Example
1. #[derive(Debug)]
2. struct Race {
3. name: String,
4. laps: Vec<i32>,
5. }
7. impl Race {
8. fn new(name: &str) -> Race { // No receiver, a static method
9. Race { name: String::from(name), laps: Vec::new() }
10. }
12. fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write access to self
13. self.laps.push(lap);
14. }
16. fn print_laps(&self) { // Shared and read-only borrowed access to self
17. println!("Recorded {} laps for {}:", self.laps.len(), self.name);
18. for (idx, lap) in self.laps.iter().enumerate() {
19. println!("Lap {idx}: {lap} sec");
20. }
21. }
23. fn finish(self) { // Exclusive ownership of self
24. let total = self.laps.iter().sum::<i32>();
25. println!("Race {} is finished, total lap time: {}", self.name, total);
26. }
27. }
29. fn main() {
30. let mut race = Race::new("Monaco Grand Prix");
31. race.add_lap(70);
32. race.add_lap(68);
33. race.print_laps();
34. race.add_lap(71);
35. race.print_laps();
36. race.finish();
37. // race.add_lap(42);
38. }
Key Points:
- All four methods here use a different method receiver.
- You can point out how that changes what the function can do with the variable values and if/how it can be used again in
main. - You can showcase the error that appears when trying to call
finishtwice. - Note that although the method receivers are different, the non-static functions are called the same way in the main body. Rust enables automatic referencing and dereferencing when calling methods. Rust automatically adds in the
&,*,mutsso that that object matches the method signature. - You might point out that
print_lapsis using a vector that is iterated over. We describe vectors in more detail in the afternoon.
