1 个不稳定版本
0.1.0 | 2020 年 9 月 9 日 |
---|
#47 在 #any
61 次每月下载
10KB
132 行
Downcast trait:一个模块,用于通过 core::any 支持向下转换 dyn 特性。此特性与 intertrait 类似,但不需要制作散列表或任何复杂的链接器魔法。在某些情况下,所有转换都会被优化掉。
此crate使用transmute(通常被认为是不安全的Rust)将未知类型作为函数的返回值传递,但随后将值转换回原始类型。
Downcast traits 允许调用者将实现 DowncastTrait 特性的 dyn 对象转换为结构体实现该特性支持的任何特性。此特性的最有用用例是,如果一个类包含实现某个特性的对象列表,并且想要在另一个也实现该特性的子集上调用函数。这类似于面向对象语言中的子类转换。
示例
- Widget 特性在图形用户界面系统中为所有小部件实现。
- widget 特性扩展了 DowncastTrait。
- 如果可以向小部件中添加子小部件,则小部件可以实现 Container 特性。
- container 有一个小部件列表,并希望对所有实现 container 的小部件调用特定函数。
#[macro_use] extern crate downcast_trait;
use downcast_trait::DowncastTrait;
use core::{any::{Any, TypeId}, mem};
trait Widget: DowncastTrait {}
trait Container: Widget {
fn enumerate_widget_leaves_recursive(&self) -> Vec<&Box<dyn Widget>>;
}
struct Window {
sub_widgets: Vec<Box<dyn Widget>>,
}
impl Widget for Window {}
impl Container for Window {
fn enumerate_widget_leaves_recursive(&self) -> Vec<&Box<dyn Widget>> {
let mut result = Vec::<&Box<dyn Widget>>::new();
self.sub_widgets.iter().for_each(|sub_widget| {
if let Some(sub_container) =
downcast_trait!(dyn Container, sub_widget.as_ref().to_downcast_trait())
{
result.extend(sub_container.enumerate_widget_leaves_recursive());
} else {
result.push(sub_widget);
}
});
result
}
}
impl DowncastTrait for Window {
downcast_trait_impl_convert_to!(dyn Container);
}