[英]How to get mutable struct from boxed trait
I'd like to modify data in a struct based on a trait that is boxed.我想根据装箱的特征修改结构中的数据。 The following code prints the value but gives me "cannot mutably borrow immutable field" when I try to change it or "cannot borrow as mutable" when calling its function.以下代码打印该值,但在我尝试更改它时给我“不能可变地借用不可变字段”或在调用其函数时“不能借用为可变字段”。
My plan is to have a vector of Ai
each containing the AiData
derived struct and then iterate over them, set some data in it and call the tick()
function.我的计划是有一个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
How to get mutable struct from boxed trait如何从盒装特征中获取可变结构
You cannot get a struct from the boxed trait object.您无法从装箱的 trait 对象中获取结构体。 You can get a reference to the struct, however.但是,您可以获得对该结构的引用。
As explained in The Rust Programming Language 's chapter on variables and mutability , mutability is a property of the binding.正如The Rust Programming Language的有关变量和可变性的章节所解释的,可变性是绑定的一个属性。 Additionally, as described in the chapter on references and borrowing , a mutable reference ( &mut T
) is distinct from an immutable reference ( &T
).此外,如引用和借用章节所述,可变引用 ( &mut T
) 与不可变引用 ( &T
) 不同。 Based on these two points, you cannot get a mutable reference from an immutable variable 1 .基于这两点,您无法从不可变变量1获得可变引用。
The code has:代码有:
Any::downcast_ref
, which returns an immutable reference调用Any::downcast_ref
,它返回一个不可变的引用When you fix all of those, the code works:当您修复所有这些时,代码将起作用:
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 You can read about interior mutability which actually does allow you to get a mutable reference from an immutable variable, at the expense of introducing runtime checks to prevent aliasing. 1您可以阅读内部可变性,它实际上允许您从不可变变量中获取可变引用,代价是引入运行时检查以防止别名。
See also:也可以看看:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.