我怎样才能从 Box<Any> 向下转型?到 trait 对象类型? [英] How can I downcast from Box&lt;Any&gt; to a trait object type?

查看:45
本文介绍了我怎样才能从 Box<Any> 向下转型?到 trait 对象类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

pub struct WidgetWrap {//...小部件:RefCell>,}

有时我想将 Box 转换为 Box

let mut cell = widget.borrow_mut();让 w = cell.downcast_mut::>();

这给了我这样的错误:

错误:实例化一个类型参数不兼容的类型`Box<WidgetTrait>`,不满足 `'static` [E0144]

这到底是什么意思?

我看过如何修复:值可能包含引用;添加绑定到 `T` 的 `'static`,并尝试在任何地方添加 + 'static.

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

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

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

解决方案

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

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

由此,您可能会看到您只能拥有一个级别的 traityness——如果您有一个 Box 并且您再次将它装箱为 Box,您只能将其作为 Box 对象取出.类似地,如果你使用一个实现 WidgetTrait 的类型 Widget 并将它装在一个 Box 中,你只能将它作为一个Widget 对象,而不是 Box 对象.

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

解决方案,如果您真的需要这些方面的解决方案(您可能不需要;坚持只使用 Box 可能是最好的方法)是有一个特性,它也实现了 Any 所做的事情.这不是目前最简单的事情,但可以做到.Teepee的Header特征是一个例子这是如何工作的;Box

对象将具有标头转换方法以及 Any.downcast_ref() 等.>

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

At some point I want to cast Box<Any> to Box<WidgetTrait>

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

This gives me an error of this kind:

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

What does this really mean?

I've looked at How to fix: value may contain references; add `'static` bound to `T` and did try adding + 'static everywhere.

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

It fixes the compile errors, but fails when I try to unwrap the downcasted box as shown above. And yes, the content of the box is an object that implements WidgetTrait.

Obviously, I am coding in Rust at a level that I don't quite understand, but maybe someone can help me get a better grip on the concepts involved in the above task.

解决方案

(I shall ignore the 'static part as it’s comparatively irrelevant for the parts I’m explaining.)

Box<Trait> for a given trait Trait is stored as two pieces of data: a pointer to the actual data in memory and a pointer to the vtable for its type’s implementation of Trait.

From that, you may see that you can only have one level of traityness—if you have a Box<WidgetTrait> and you box it again as Box<Any>, you would only be able to get it out as a Box<WidgetTrait> object. Similarly, if you take a type Widget that implements WidgetTrait and box it in a Box<Any>, you can only get it out as a Widget object, not as a Box<WidgetTrait> object.

Such is the nature of the type IDs being used internally: unlike in a dynamic or VM-based language, the type system is purely a compile-time construct; there is no such thing as the type system at runtime.

The solution, if you really need a solution along these lines (you probably don’t; sticking with just a Box<WidgetTrait> is probably the best way) is to have a trait which also implements what Any does. This is not the simplest thing at present, but can be done. Teepee’s Header trait is an example of how this can work; a Box<Header> object will have the header-transforming methods as well as Any’s .downcast_ref() and so forth.

这篇关于我怎样才能从 Box<Any> 向下转型?到 trait 对象类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆