Rust 我可以用trait对象进行类型内省,然后对其进行降级吗?
我有一个Rust 我可以用trait对象进行类型内省,然后对其进行降级吗?,rust,Rust,我有一个Trait的集合,一个迭代它并执行某些操作的函数,然后我想检查实现器类型,如果它是Foo类型,则将其向下转换并调用一些Foo方法 基本上,类似于围棋的东西 四处搜索我找到了,但它只能在静态类型上实现 要帮助演示我想要的内容,请执行以下操作: let vec: Vec<Box<Trait>> = // for e in vec.iter() { e.trait_method(); // if typeof e == Foo { // le
Trait
的集合,一个迭代它并执行某些操作的函数,然后我想检查实现器类型,如果它是Foo
类型,则将其向下转换并调用一些Foo方法
基本上,类似于围棋的东西
四处搜索我找到了,但它只能在静态类型上实现
要帮助演示我想要的内容,请执行以下操作:
let vec: Vec<Box<Trait>> = //
for e in vec.iter() {
e.trait_method();
// if typeof e == Foo {
// let f = e as Foo;
// f.foo_method();
//}
}
让vec:vec=//
对于vec.iter()中的e{
e、 特征_方法();
//如果类型e==Foo{
//设f=e为Foo;
//f.foo_方法();
//}
}
正如您所注意到的,向下投射只适用于任何
特征,是的,它只支持静态
数据。你可以找到最近关于为什么会这样的讨论。基本上,实现任意生命周期的引用的反射是困难的
也不可能(至少到目前为止)轻松地将任何
与您的定制特征结合起来。然而,最近已经为您的trait创建了一个自动实现Any
。你也可以找到一些关于它的讨论。这不是一个特定于锈蚀的问题,尽管词汇可能有点不同。解决此类问题的理想方法,不仅是Rust中的Trait,而且是任何语言中的Trait,是将所需的行为(foo_method
,在您的示例中)添加到抽象接口(Trait
):
as_any
必须是Trait
中的方法,因为它需要访问具体类型。现在,您可以尝试对Trait
Trait对象调用Foo
方法,如下所示():
if let Some(r)=downcast::(trait\u object\u ref){
r、 foo_方法();
}
要实现这一点,您必须指定所需的类型(:
),并使用if let
处理当引用对象不是Foo
的实例时发生的情况。除非确切知道具体类型,否则不能将trait对象向下转换为具体类型
但是如果你需要知道具体的类型,trait对象几乎毫无用处!您可能应该改为使用enum
,这样,如果忽略处理某个变量,就会出现编译时错误。此外,您不能将Any
与非静态
结构一起使用,因此如果任何Foo
可能需要包含引用,则此设计是死路一条。如果你能做到的话,最好的解决办法是在特质本身中添加foo\u方法。你确定你需要向下投射(应该尽可能避免)?如果您控制Trait
或Foo
,您很可能会避免它。这似乎是Enum
s的目标场景。@goertzenator您能提供一个示例吗?我面临着几乎相同的问题,不知道如何正确使用枚举来解决这个问题。提前谢谢
trait Trait {
fn trait_method(&self);
fn foo_method(&self) {} // does nothing by default
}
struct Foo;
impl Trait for Foo {
fn trait_method(&self) {
println!("In trait_method of Foo");
}
fn foo_method(&self) { // override default behavior
println!("In foo_method");
}
}
struct Bar;
impl Trait for Bar {
fn trait_method(&self) {
println!("In trait_method of Bar");
}
}
fn main() {
let vec: Vec<Box<Trait>> = vec![Box::new(Foo), Box::new(Bar)];
for e in &vec {
e.trait_method();
e.foo_method();
}
}
use std::any::Any;
trait Trait {
fn as_any(&self) -> &Any;
}
struct Foo;
impl Trait for Foo {
fn as_any(&self) -> &Any {
self
}
}
fn downcast<T: Trait + 'static>(this: &Trait) -> Option<&T> {
this.as_any().downcast_ref()
}
if let Some(r) = downcast::<Foo>(trait_object_ref) {
r.foo_method();
}