#traits #cast #any

downcast-trait

允许在特性之间进行转换

1 个不稳定版本

0.1.0 2020 年 9 月 9 日

#47#any

Download history 16/week @ 2024-03-28 14/week @ 2024-04-04

61 次每月下载

MIT/Apache

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);
}

无运行时依赖