- Mastering Rust
- Rahul Sharma Vesa Kaihlavirta
- 539字
- 2021-07-02 13:35:16
Impl blocks on structs
We can add behavior to our previously defined Player struct with two functionalities: a constructor-like function that takes a name and sets default values for the remaining fields in Person, and getter and setter methods for the friend count of Person:
// struct_methods.rs
struct Player {
name: String,
iq: u8,
friends: u8
}
impl Player {
fn with_name(name: &str) -> Player {
Player {
name: name.to_string(),
iq: 100,
friends: 100
}
}
fn get_friends(&self) -> u8 {
self.friends
}
fn set_friends(&mut self, count: u8) {
self.friends = count;
}
}
fn main() {
let mut player = Player::with_name("Dave");
player.set_friends(23);
println!("{}'s friends count: {}", player.name, player.get_friends());
// another way to call instance methods.
let _ = Player::get_friends(&player);
}
We use the impl keyword, followed by the type we are implementing the methods for, followed by braces. Within braces, we can write two kinds of methods:
- Associated methods: Methods without a self type as their first parameter. The with_name method is called an associated method because it does not have self as the first parameter. It is similar to a static method in object-oriented languages. These methods are available on the type themselves and do not need an instance of the type to invoke them. Associated methods are invoked by prefixing the method name with the struct name and double colons, like so:
Player::with_name("Dave");
- Instance methods: Functions that take a self value as its first argument. The self symbol here is similar to self in Python and points to the instance on which the method is implemented (here, this is Player). Therefore, the get_friends() method can only be called on already created instances of the struct:
let player = Player::with_name("Dave");
player.get_friends();
If we were to call get_friends with the associated method syntax, that is, Player::get_friends(), the compiler gives the following error:

The error is misleading here, but it indicates that instance methods are basically associated methods with self as the first parameter and that instance.foo() is a syntax sugar. This means that we can call it like this, too: Player::get_friends(&player);. In this invocation, we pass the method an instance of Player, that is, &self is &player.
There are three variants of instance methods that we can implement on types:
- self as the first parameter. In this case, calling this method won't allow you to use the type later.
- &self as the first parameter. This method only provides read access to the instance of a type.
- &mut self as the first parameter. This method provides mutable access to the instance of a type.
Our set_friends method is a &mut self method, which allows us to mutate the fields of player. We need the & operator before self, meaning that self is borrowed for the duration of the method, which is exactly what we want here. Without the ampersand, the caller would move the ownership to the method, which means that the value would get de-allocated after get_friends returns and we would not get to use our Player instance anymore. Don't worry if the terms move and borrowing does not make sense as we explain all of this in Chapter 5, Memory Management and Safety.
Now, onto implementations for enums.
- 控糖控脂健康餐
- UML+OOPC嵌入式C語言開發精講
- 高級C/C++編譯技術(典藏版)
- Mastering AndEngine Game Development
- Visual Basic程序設計實驗指導(第4版)
- PLC編程與調試技術(松下系列)
- R Data Analysis Cookbook(Second Edition)
- Instant Ext.NET Application Development
- 移動界面(Web/App)Photoshop UI設計十全大補
- C語言程序設計
- 虛擬現實建模與編程(SketchUp+OSG開發技術)
- 軟硬件綜合系統軟件需求建模及可靠性綜合試驗、分析、評價技術
- 量子計算機編程:從入門到實踐
- 網頁設計與制作
- Jakarta EE Cookbook