官术网_书友最值得收藏!

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.

主站蜘蛛池模板: 家居| 阿尔山市| 达州市| 定远县| 错那县| 大同市| 海兴县| 象山县| 柘荣县| 泰顺县| 巴楚县| 翼城县| 涿鹿县| 无极县| 秀山| 安国市| 拉孜县| 莒南县| 句容市| 特克斯县| 水富县| 开封市| 本溪市| 察隅县| 确山县| 华宁县| 阜平县| 茂名市| 酒泉市| 分宜县| 平昌县| 乌拉特前旗| 贞丰县| 娄烦县| 大丰市| 唐河县| 琼海市| 阿勒泰市| 洞头县| 莱芜市| 无棣县|