Any
Any
trait 常用于 trait object
, 用于实现类型反射.
有几种使用形式:
&dyn Any
, 调用downcast_ref()
, 得到只读引用&mut dyn Any
, 调用downcast_mut()
, 得到可变更引用Box<dyn Any>
, 调用downcast()
方法, 得到Box<T>
比如:
#![allow(unused)] fn main() { 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()
时, 应先把它们转成引用:
#![allow(unused)] fn main() { 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.