與 Rust 編譯器的鬥爭 - 6

在上一篇文章中,我們討論了與 trait 生命週期相關的編譯器錯誤。特別是,我們看到了 Box 被隱式轉換爲 Box<dyn Trait + 'static>。

在前面的例子中,我們所使用的所有特徵對象都滿足'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();
    }
}

有了這個改變,玩家結構體不僅可以接受靜態的,也可以接受非靜態的武器特徵對象!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/FPpPiuheSm4bG_S2t05-cg