簡體   English   中英

如何從盒裝特征中獲取可變結構

[英]How to get mutable struct from boxed trait

我想根據裝箱的特征修改結構中的數據。 以下代碼打印該值,但在我嘗試更改它時給我“不能可變地借用不可變字段”或在調用其函數時“不能借用為可變字段”。

我的計划是有一個Ai向量,每個向量都包含AiData派生結構,然后迭代它們,在其中設置一些數據並調用tick()函數。

use std::any::Any;

pub trait AiData {
    fn tick(&mut self);
    fn as_any(&self) -> &Any;
}

pub struct Ai {
    pub ai_data: Box<AiData>,
}

impl Ai {
    pub fn new(ai_data: Box<AiData>) -> Ai {
        Ai { ai_data: ai_data }
    }
}

pub struct TestAi {
    pub index: u8,
}

impl TestAi {
    pub fn new() -> TestAi {
        TestAi { index: 1 }
    }
}

impl AiData for TestAi {
    fn tick(&mut self) {
        println!("tick");
    }

    fn as_any(&self) -> &Any {
        self
    }
}

fn main() {
    let ai_data: TestAi = TestAi::new();
    let ai: Ai = Ai::new(Box::new(ai_data));

    let b: &TestAi = match ai.ai_data.as_any().downcast_ref::<TestAi>() {
        Some(b) => b,
        None => panic!("&a isn't a B!"),
    };
    println!("{:?}", b.index);

    b.tick();
    b.index = 2;
}
error[E0596]: cannot borrow immutable borrowed content `*b` as mutable
  --> src/main.rs:48:5
   |
48 |     b.tick();
   |     ^ cannot borrow as mutable

error[E0594]: cannot assign to immutable field `b.index`
  --> src/main.rs:49:5
   |
49 |     b.index = 2;
   |     ^^^^^^^^^^^ cannot mutably borrow immutable field

如何從盒裝特征中獲取可變結構

您無法從裝箱的 trait 對象中獲取結構體。 但是,您可以獲得對該結構的引用。

正如The Rust Programming Language的有關變量和可變性的章節解釋的,可變性是綁定的一個屬性。 此外,如引用和借用章節所述,可變引用 ( &mut T ) 與不可變引用 ( &T ) 不同。 基於這兩點,您無法從不可變變量1獲得可變引用。

代碼有:

  • 不可變變量
  • 對該變量的不可變引用
  • 調用Any::downcast_ref ,它返回一個不可變的引用

當您修復所有這些時,代碼將起作用:

use std::any::Any;

pub trait AiData {
    fn tick(&mut self);
    fn as_any_mut(&mut self) -> &mut Any;
}

pub struct Ai {
    pub ai_data: Box<AiData>,
}

impl Ai {
    pub fn new(ai_data: Box<AiData>) -> Ai {
        Ai { ai_data }
    }
}

pub struct TestAi {
    pub index: u8,
}

impl TestAi {
    pub fn new() -> TestAi {
        TestAi { index: 1 }
    }
}

impl AiData for TestAi {
    fn tick(&mut self) {
        println!("tick");
    }

    fn as_any_mut(&mut self) -> &mut Any {
        self
    }
}

fn main() {
    let ai_data = TestAi::new();
    let mut ai = Ai::new(Box::new(ai_data));

    let b = ai.ai_data
        .as_any_mut()
        .downcast_mut::<TestAi>()
        .expect("&a isn't a B!");
    println!("{:?}", b.index);

    b.tick();
    b.index = 2;
}

1您可以閱讀內部可變性,它實際上允許您從不可變變量中獲取可變引用,代價是引入運行時檢查以防止別名。

也可以看看:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM