Generics 我如何铸造Rc<;RefCell<;混凝土类型>&燃气轮机;至Rc<;RefCell<;dyn性状>>;?

Generics 我如何铸造Rc<;RefCell<;混凝土类型>&燃气轮机;至Rc<;RefCell<;dyn性状>>;?,generics,rust,trait-objects,Generics,Rust,Trait Objects,我试图将Rc转换为Rc(数据实现接口),但在通用方法中不可能: use std::cell::RefCell; use std::rc::Rc; trait Interface { fn pouet(&self); } struct Data {} impl Interface for Data { fn pouet(&self) { println!("pouet"); } } fn helper<T&g

我试图将
Rc
转换为
Rc
数据
实现
接口
),但在通用方法中不可能:

use std::cell::RefCell;
use std::rc::Rc;

trait Interface {
    fn pouet(&self);
}

struct Data {}

impl Interface for Data {
    fn pouet(&self) {
        println!("pouet");
    }
}

fn helper<T>(o: &Rc<RefCell<T>>)
where
    T: Interface,
{
    let t = o as &Rc<RefCell<dyn Interface>>;
    work(t);
}

fn work(o: &Rc<RefCell<dyn Interface>>) {
    o.borrow().pouet();
}

fn main() {
    // work
    {
        let o = Rc::new(RefCell::new(Data {}));
        work(&(o as Rc<RefCell<dyn Interface>>));
    }
    // raise an compile error
    {
        let o = Rc::new(RefCell::new(Data {}));
        helper(&o);
    }
}
使用std::cell::RefCell;
使用std::rc::rc;
特征接口{
fn-pouet(和self);
}
结构数据{}
impl数据接口{
fn pouet(和self){
println!(“pouet”);
}
}
fn助手(o:&Rc)
哪里
T:接口,
{
设t=o as&Rc;
工作(t);
}
fn工程(o:&Rc){
o、 借().pouet();
}
fn main(){
//工作
{
设o=Rc::new(RefCell::new(Data{}));
工作(&(o作为Rc));
}
//引发编译错误
{
设o=Rc::new(RefCell::new(Data{}));
助手(&o);
}
}
我在非基本类型转换上有一个编译错误:

error[E0605]:非原语强制转换:`&Rc`as`&Rc`
-->src/main.rs:20:13
|
20 |设t=o as&Rc;
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

非常感谢,我理解

解决办法是

fn helper<T>(o: &Rc<RefCell<T>>)
where
    T: Interface + 'static,
{
    let t = o.clone() as Rc<RefCell<dyn Interface>>;
    work(&t);
}
fn助手(o:&Rc)
哪里
T:接口+'静态,
{
设t=o.clone()为Rc;
工作与技术;
}

fn助手(o:Rc)
哪里
T:接口+'静态,
{
设t=o为Rc;
工作与技术;
}

感谢

与Java等语言不同,对trait对象的强制转换实际上修改了数据(必须添加vtable),这意味着您必须借用refcell。强制转换值并不是简单地重新解释类型,因此您必须实际借用refcell,以便可以对值进行变异。另请参见,问题是,结构只包含它们的数据。例如,
struct Foo{field:u8}
的大小为1字节。但是,为了将我们的对象用作trait对象(将其视为实现trait的随机对象),我们现在必须将其存储在一个函数表中,该函数表描述如何使用它,称为vtable。vtable只是一个表,它指向我们对trait的实现。假设我们有一个trait
MyTrait
和一个方法
run()
,我们有结构
Foo
Bar
实现
MyTrait
,然后我们有一个
Vec
包含许多
Foo
s和
Bar
s。每个trait对象(
dyn MyTrait
)必须包含一个指向其版本的
run()
的指针,以便我们知道如何调用它。回到问题上来,问题是你需要存储一个指向trait中所有方法的指针表,以便能够使用它。
fn helper<T>(o: Rc<RefCell<T>>)
where
    T: Interface + 'static,
{
    let t = o as Rc<RefCell<dyn Interface>>;
    work(&t);
}