Downcasting和Box <Any>

por*_*uod 6 downcast rust

pub struct WidgetWrap {
    // ...
    widget: RefCell<Box<Any>>,
}
Run Code Online (Sandbox Code Playgroud)

在某些时候,我想投Box<Any>Box<WidgetTrait>

let mut cell = widget.borrow_mut();
let w = cell.downcast_mut::<Box<WidgetTrait>>();
Run Code Online (Sandbox Code Playgroud)

这给了我这样的错误:

error: instantiating a type parameter with an incompatible type
`Box<WidgetTrait>`, which does not fulfill `'static` [E0144]
Run Code Online (Sandbox Code Playgroud)

这究竟意味着什么?

我看过如何解决:值可能包含引用; 添加`'static`绑定到`T`并尝试添加+ 'static到处.

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

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

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

Chr*_*gan 11

(我将忽略该'static部分,因为它与我正在解释的部分相比无关紧要.)

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

从那以后,你可能会发现你只能拥有一个级别的特权 - 如果你有一个Box<WidgetTrait>并且你再次Box<Any>将它包装起来,你只能将它作为一个Box<WidgetTrait>对象来获取.类似地,如果你采用一种Widget实现WidgetTrait并将其封装在a中的类型Box<Any>,你只能将它作为一个Widget对象而不是一个Box<WidgetTrait>对象.

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

解决方案,如果你真的需要这些方面的解决方案(你可能不这样做;坚持只是一个Box<WidgetTrait>可能是最好的方法)就是有一个特性也可以实现Any.这不是目前最简单的事情,但可以做到.圆锥形帐篷的Header特性是一个如何运作的例子; 一个Box<Header>对象将具有首标转换方法以及Any.downcast_ref()等等.