我对 Rust 很陌生,所以如果这是一个简单的问题,我深表歉意!
我有以下简化场景,其中我有一个特征和两个实现该特征的结构类型(TypeA 和 TypeB)。然后我有一个特征向量,其中包含 TypeA 和 TypeB 的实例。
稍后,我想根据类型迭代仅属于 TypeA 或 TypeB 的向量和访问字段。下面是我写的。我的尝试是匹配每个项目的类型,然后将装箱特征迭代器向下转换为结构。这适用于
&
引用,但如何实现可变引用 &mut
。
对于
&
参考,请考虑以下...
use std::any::Any;
trait MyTrait {
fn do_something(&self);
fn as_any(&self) -> &dyn Any;
}
struct TypeA{field_a: u16}
impl MyTrait for TypeA {
fn do_something(&self) {
println!("TypeA is doing something.");
}
fn as_any(&self) -> &dyn Any {
self
}
}
struct TypeB{field_b: u16}
impl MyTrait for TypeB {
fn do_something(&self) {
println!("TypeB is doing something.");
}
fn as_any(&self) -> &dyn Any {
self
}
}
fn main() {
let vec: Vec<Box<dyn MyTrait>> = vec![
Box::new(TypeA{field_a:10}),
Box::new(TypeB{field_b:20}),
];
for item in &vec {
// Downcast the trait object to its concrete type
if let Some(type_a) = item.as_any().downcast_ref::<TypeA>() {
type_a.do_something();
print!("{}", type_a.field_a);
} else if let Some(type_b) = item.as_any().downcast_ref::<TypeB>() {
type_b.do_something();
print!("{}", type_b.field_b);
} else {
println!("Unknown type");
}
}
}
但是,我想修改向下转型实例中的字段,例如
type_a.field_a = 100;
如果您添加一种方法来获得
&mut dyn Any
的特质,您就可以做到这一点:
fn as_any_mut(&mut self) -> &mut dyn Any;
实现方式与
as_any
相同:
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
您还需要使
vec
可变,并迭代 &mut vec
而不是 &vec
,然后您就可以执行此操作,例如:
item.as_any_mut().downcast_mut::<TypeA>()
这会给你一个
&mut TypeA
。
但是,我强烈建议您消费者使用枚举而不是盒装特征对象。如果您需要支持一组封闭的变体,这将更加符合人体工程学。