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

问题描述 投票:-2回答:1

我想基于盒装的特征修改结构中的数据。下面的代码打印了这个值,但是当我尝试更改它时,“不能可变地借用不可变字段”或者在调用它的函数时“不能借用可变字段”。

我的计划是有一个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
rust
1个回答
1
投票

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

您无法从盒装特征对象中获取结构。但是,您可以获得对结构的引用。

作为explained in The Rust Programming Language's chapter on variables and mutability,可变性是绑定的属性。另外,如the chapter on references and borrowing中所述,可变参考(&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您可以阅读有关interior mutability的内容,它实际上允许您从不可变变量中获取可变引用,但代价是引入运行时检查以防止别名。

也可以看看:

© www.soinside.com 2019 - 2024. All rights reserved.