Any
Any trait 常用于 trait object, 用于实现类型反射.
有几种使用形式:
&dyn Any, 调用downcast_ref(), 得到只读引用&mut dyn Any, 调用downcast_mut(), 得到可变更引用Box<dyn Any>, 调用downcast()方法, 得到Box<T>
比如:
use std::any::Any;
let b: Box<dyn Any> = Box::new("hello".to_owned());
assert!(b.downcast::<String>().is_ok());
智能指针
比如 Box<dyn Any> 或者 Arc<dyn Any>, 在获取 type_id()时, 应先把它们转成引用:
use std::any::{Any, TypeId};
let b: Box<dyn Any> = Box::new(42_i32);
let actual_id = ( & * b).type_id();
assert_eq!(actual_id, TypeId::of::<i32>());
向上转型
有时候, 我们需要从一个 trait object 转型为一个具体的类型, 举个例子:
接口部分的代码 (platform.rs):
pub trait Platform {
fn rect(&self, element: dyn Element) -> Rect;
fn scale(&self) -> Option<Scale>;
}
pub struct State {
platform: Rc<dyn Platform>,
}
特定平台实现的代码 (canvas_platform.rs):
pub struct CanvasPlatform {
...
}
impl Platform for CanvasPlatform {
...
}
这里, State 结构体里面只存放了一个 Platform trait object, 我们并不能直接调用 CanvasPlatform
对象特有的方法. 为此, 可以给 Platform trait 添加一个特别的方法, 让它能转换成 Any trait:
pub trait Platform {
fn as_any(&self) -> &dyn Any;
...
}
然后为 CanvasPlatform 实现这个方法:
impl Platform for CanvasPlatform {
#[inline]
#[must_use]
fn as_any(&self) -> &dyn Any {
self
}
}
更复杂的转型可以考虑使用第三方库 bevy_reflect.