Downcasting and Box<Any>

馋奶兔 提交于 2019-11-27 05:36:23

(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.

The original code works as-is in at least Rust 1.25; presumably there was a bug or limitation in the compiler that has since been fixed:

use std::any::Any;
use std::cell::RefCell;

trait WidgetTrait {}

fn example(widget: RefCell<Box<Any>>) {
    let mut cell = widget.borrow_mut();
    let w = cell.downcast_mut::<Box<WidgetTrait>>();
}

fn main() {}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!