如何从 Box 向下转换为特征对象类型?

2024-01-07

pub struct WidgetWrap {
    // ...
    widget: RefCell<Box<Any>>,
}

在某个时候我想投射Box<Any> to Box<WidgetTrait>

let mut cell = widget.borrow_mut();
let w = cell.downcast_mut::<Box<WidgetTrait>>();

这给了我这样的错误:

error: instantiating a type parameter with an incompatible type
`Box<WidgetTrait>`, which does not fulfill `'static` [E0144]

这究竟意味着什么?

我看过如何修复:值可能包含引用;添加绑定到“T”的“static” https://stackoverflow.com/questions/24375771/how-to-fix-value-may-contain-references-add-static-bound-to-t并尝试添加+ 'static到处。

pub struct WidgetWrap {
    // ...
    widget: RefCell<Box<Any + 'static>>,
}
let mut cell = widget.borrow_mut();
let w = cell.downcast_mut::<Box<WidgetTrait + 'static>>();

它修复了编译错误,但当我尝试打开向下转换的框时失败,如上所示。是的,盒子的内容是一个实现WidgetTrait.

显然,我在 Rust 中编码的水平我不太理解,但也许有人可以帮助我更好地掌握上述任务中涉及的概念。


(我将忽略'static部分,因为它与我正在解释的部分相对无关。)

Box<Trait>对于给定的特征Trait被存储为两部分数据:一个指向内存中实际数据的指针和一个指向其类型实现的 vtable 的指针Trait.

由此,你可能会发现,你只能拥有一种特质——如果你有Box<WidgetTrait>然后你再次将其装箱为Box<Any>,你只能将其作为Box<WidgetTrait>目的。同样,如果您采用类型Widget实现WidgetTrait并将其装在一个Box<Any>,你只能把它作为Widget对象,而不是作为Box<WidgetTrait> object.

这就是内部使用的类型 ID 的本质:与动态或基于 VM 的语言不同,类型系统纯粹是编译时构造;运行时不存在类型系统这样的东西.

解决方案,如果你真的need沿着这些思路的解决方案(你可能不会;坚持只用Box<WidgetTrait>可能是最好的方法)是拥有一个也实现什么的特征Any做。这不是目前最简单的事情,但是是可以做到的。圆锥形帐篷的Header trait https://github.com/teepee/teepee/blob/17d69d7f3ba0c9be51538148d6d7e47d7f474486/src/httpcommon/headers/mod.rs这是一个如何运作的例子; ABox<Header>对象将具有标头转换方法以及Any’s .downcast_ref()等等。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 Box 向下转换为特征对象类型? 的相关文章

随机推荐