Any
特质,并且仅支持 'static
数据。你可以在这里找到一个关于为什么会这样的最近讨论:http://www.reddit.com/r/rust/comments/2r25rf/why_does_any_only_work_for_t_static/。基本上,为任意生命周期的引用实现反射是困难的。Any
轻松地结合起来也是不可能的。但是,最近创建了一个用于自动实现你的特质 Any
的 宏库。你也可以在这里找到有关它的一些讨论:http://www.reddit.com/r/rust/comments/2ricdw/mopa_my_own_personal_any_a_macro_to_implement_all/。虽然词汇可能有些不同,但这并不是Rust特有的问题。解决这种问题的理想方法(不仅在Rust中,而且在任何语言中)是将所需的行为(例如您示例中的foo_method
)添加到抽象接口(Trait
)中:
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<dyn 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) -> &dyn Any;
}
struct Foo;
impl Trait for Foo {
fn as_any(&self) -> &dyn Any {
self
}
}
fn downcast<T: Trait + 'static>(this: &dyn Trait) -> Option<&T> {
this.as_any().downcast_ref()
}
as_any
必须是Trait
中的方法,因为它需要访问具体类型。现在,你可以像这样在Trait
特征对象上尝试调用Foo
方法(完整的演示示例):
if let Some(r) = downcast::<Foo>(&**e) {
r.foo_method();
}
::<Foo>
),并使用if let
处理引用对象不是Foo
实例时的情况。除非您确切地知道具体类型,否则无法将一个trait对象向下转换为具体类型。enum
,这样在某个地方省略处理变量时,将会得到编译时错误。此外,您无法将Any
与非'static
结构体一起使用。因此,如果任何Foo
可能需要包含引用,则此设计是死路一条。如果可以的话,最好的解决方案是将foo_method
添加到trait本身中。
Trait
或Foo
中的任意一个,你很可能可以避免使用它。 - Matthieu M.枚举
所设计的场景。 - goertzenator