Rust 如何从装箱特征中获取可变结构

Rust 如何从装箱特征中获取可变结构,rust,Rust,我想根据装箱的特征修改结构中的数据。下面的代码打印该值,但当我尝试更改它时,会给出“不能可变地借用不可变字段”,或者在调用其函数时给出“不能作为可变字段借用” 我的计划是让Ai的向量包含AiData派生结构,然后迭代它们,在其中设置一些数据并调用tick()函数 use std::any::Any; pub trait AiData { fn tick(&mut self); fn as_any(&self) -> &Any; } pub str

我想根据装箱的特征修改结构中的数据。下面的代码打印该值,但当我尝试更改它时,会给出“不能可变地借用不可变字段”,或者在调用其函数时给出“不能作为可变字段借用”

我的计划是让
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;
}
如何从装箱特征中获取可变结构

无法从装箱的trait对象获取结构。但是,您可以获得对结构的引用

正如所述,可变性是绑定的一个属性。此外,如中所述,可变引用(
&mut T
)不同于不可变引用(
&T
)。基于这两点,您无法从不可变变量1获得可变引用

守则包括:

  • 不可变变量
  • 对该变量的不可变引用
  • 调用
    Any::downcast\u 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;
}
使用std::any::any;
阿依达酒店{
fn勾选(&mut self);
fn as_any_mut(&mut self)->&mut any;
}
发布结构Ai{
pub ai_data:Box,它实际上允许您从不可变变量获取可变引用,但代价是引入运行时检查以防止别名

另见:


是什么让你相信你可以从这个不可变的变量中得到一个可变的引用?你已经读过免费的官方书籍了吗?这本书解释了诸如可变性之类的概念。谢谢你的快速回答。诀窍是我确实试着用与你相同的方式来改变特性,并相应地修正了impl和downcast_mut,但它对我不起作用因为我错过了“let b:&mut TestAi…”。取而代之的是“let mut b:&TestAi”。@Skemp没有理由从这里开始使用显式类型。惯用的Rust会避开它们。我只是习惯于从其他语言中这样做,而且对我来说也更具可读性。@Skemp How
let ai_data:TestAi=TestAi::new()
更具可读性?这就像,例如,用C编写
FooBar f=new FooBar();
一样。你复制信息没有任何好处。此外,如果你想复制一些无关的外国习惯用法(对任何语言都一样),您走错了。@Boiethios在本例中的可读性没有提高。但在本例中,
让b:&TestAi=match ai.ai_data.as_any().downcast_ref:(){Some(b)=>b,None=>panic!(“&a不是b!”,}
至少对我来说是这样。此外,我对noob很信任,但我正在努力改进。