在上一篇文章中,我们讨论了与trait生命周期相关的编译器错误。特别是,我们看到了Box
在前面的例子中,我们所使用的所有特征对象都满足'static生命周期,但是如果我们想要将武器特征对象的生命周期限制放宽为非静态呢?
代码如下:
trait Weapon {
fn fire(&self);
}
struct Player {
weapon: Box<dyn Weapon>,
}
impl Player {
fn new(weapon: impl Weapon + 'static) -> Self {
Self { weapon: Box::new(weapon) }
}
fn change_weapon(&mut self, weapon: impl Weapon + 'static) {
self.weapon = Box::new(weapon);
}
fn shoot(&self) {
self.weapon.fire();
}
}
struct CustomWeapon<'a> {
sound: &'a str
}
impl<'a> CustomWeapon<'a> {
fn new(sound: &'a str) -> Self {
Self { sound }
}
}
impl<'a> Weapon for CustomWeapon<'a> {
fn fire(&self) {
println!("{}", self.sound)
}
}
fn main() {
let impact = String::from("pew pew"); // non-static
let player = Player::new(CustomWeapon::new(&impact));
player.shoot(); // pew pew
}
与前面的例子不同的是,现在CustomWeapon有一个对非静态对象的引用。
error[E0597]: `impact` does not live long enough
--> src/main.rs:42:48
|
41 | let impact = String::from("pew pew");
| ------ binding `impact` declared here
42 | let player = Player::new(CustomWeapon::new(&impact));
| ------------------------------^^^^^^^--
| | |
| | borrowed value does not live long enough
| argument requires that `impact` is borrowed for `'static`
43 | player.shoot(); // pew pew
44 | }
| - `impact` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
正如预期的那样,编译器抱怨impact对象不是静态的。修复方法是引入生命周期泛型并替换'static,代码修改如下:
struct Player<'a> {
weapon: Box<dyn Weapon + 'a>,
}
impl<'a> Player<'a> {
fn new(weapon: impl Weapon + 'a) -> Self {
Self { weapon: Box::new(weapon) }
}
fn change_weapon(&mut self, weapon: impl Weapon + 'a) {
self.weapon = Box::new(weapon);
}
fn shoot(&self) {
self.weapon.fire();
}
}
有了这个改变,玩家结构体不仅可以接受静态的,也可以接受非静态的武器特征对象!
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8