繁体   English   中英

Rust Trait对象转换

[英]Rust Trait object conversion

由于此错误的两个实例,以下代码将无法编译:

错误[E0277]:特征绑定Self: std::marker::Sized不满足

我不明白为什么在这个实例中需要Sized因为&self&Any都是指针而且操作不需要知道实现特征的结构的大小,它只需要知道指针本身及其类型。转换和转换,因为&self在特征中实现时是通用的。

我认为这可能是编译器强制执行不必要的约束的一个实例,我考虑过使用生锈的GitHub仓库提出问题,但我想我应该看看,在我提出问题之前,有人在这里知道我不知道的事情。

use std::any::Any;

trait Component: Any {
    fn as_any(&self) -> &Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut Any {
        self
    }
}

替代方法是为实现此特征的结构使as_any()as_any_mut()必需的函数,但对于这些结构,实现将始终完全按照此处显示到每个单独的字符,从而生成相同样板的多个实例码。

动态大小的类型也可以实现特征。 特别是,当您定义对象安全特征时,编译器还会定义一个动态大小的类型,其名称与特征相同,这使您可以使用对象类型,如&Component

诸如&Component&Any类的对象类型不仅仅是普通的指针; 他们是胖子 胖指针结合了指向数据的指针和另一个数据:对于对象类型,它是指向vtable的指针; 对于切片,它是切片的长度。

当从常规指针(例如&Button )转换为对象类型时,编译器静态地知道将哪个vtable放入胖指针(例如Button的vtable for Any )。 另一方面,Rust不支持从对象类型转换为另一个对象类型(例如,从&Component&Any ),因为对象中没有足够的数据来初始化新的胖指针。 这就是编译器将此注释添加到错误消息的原因:

= note: required for the cast to the object type `std::any::Any + 'static`

有两种方法可以解决这个问题:

  1. 要求实现Component所有类型都要调整Sized

     trait Component: Any + Sized { fn as_any(&self) -> &Any { self } fn as_any_mut(&mut self) -> &mut Any { self } } 

    这导致您将无法使用对象类型,例如&ComponentBox<Component>

  2. 使as_anyas_any_mut方法仅在Self Sized时可用:

     trait Component: Any { fn as_any(&self) -> &Any where Self: Sized { self } fn as_any_mut(&mut self) -> &mut Any where Self: Sized { self } } 

    这样,您仍然可以使用特征的对象类型,但是您无法在它们上调用as_anyas_any_mut

我发现我认为是一个不需要新编译器功能的优秀解决方案。

pub trait Component {
    // ...
}

pub trait ComponentAny: Component + Any {
    fn as_any(&self) -> &Any;
    fn as_any_mut(&mut self) -> &mut Any;
}

impl<T> ComponentAny for T
    where T: Component + Any
{
    fn as_any(&self) -> &Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut Any {
        self
    }
}

从这里开始,我只需更改所有API以接受ComponentAny而不是Component 因为Any自动对任何实施'static类型, ComponentAny现在自动为任何实现'static实现类型Component 感谢有没有办法结合多个特征来定义新的特征? 为了这个想法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM