将trait对象重新装箱为一般实现的trait



到目前为止,我很少遇到Rust的类型推断问题,但我担心我不太理解以下代码的问题:

trait SpecificTrait {}
struct SpecificStruct;
impl SpecificTrait for SpecificStruct {}
trait GeneralTrait {}
impl<T: SpecificTrait> GeneralTrait for T {}
fn new_specific_box() -> Box<dyn SpecificTrait> {
Box::new(SpecificStruct {})
}
fn new_general_box(from_specific_box: bool) -> Box<dyn GeneralTrait> {
if from_specific_box {
new_specific_box()
} else {
Box::new(SpecificStruct {})
}
}

游乐场

我认为这与Rust可能仍然不支持upcasting有关,尽管在这段代码中,SpecificTrait不需要GeneralTrait,而是在所有实现SpecificTrait的类型上通用地实现了更通用的特性。

我知道trait对象类型是不同的(这导致了上面代码中的错误(,但我希望类型推断能够确认每个dyn SpecificTrait对象也应该表示为dyn GeneralTrait对象。然而,我也不能简单地铸造Box<dyn SpecificTrait> as Box<dyn GeneralTrait>

那么,我该如何(通过语言(将我的Box<dyn SpecificTrait>重新表达为Box<dyn GeneralTrait>呢?

我希望类型推断能够确认每个dyn SpecificTrait对象也应该表示为dyn GeneralTrait对象

但事实并非如此。CCD_ 11包括指向"0"的指针;虚拟表";指向SpecificTrait方法的函数指针,并且您无法从中获得指向GeneralTrait对应虚拟表的指针。您链接的问题的一个答案详细解释了子等待的问题,但

在实现SpecificTrait的所有类型上通用地实现了更通用的特性

让情况变得更糟。对于子轮次,超性状的方法至少存在于子轮次vtable中(在该答案中为24- |methods of Self and supertraits(。通过一揽子实施,它们不是。

另一个答案解释了为什么不能简单地转换trait对象来获得所需的结果。然而,有一个变通方法:

impl SpecificTrait for Box<dyn SpecificTrait>{}
fn new_general_box(from_specific_box: bool) -> Box<dyn GeneralTrait> {
if from_specific_box {
Box::new(new_specific_box())
} else {
Box::new(SpecificStruct {})
}
}

换句话说,只需为装箱的特征对象实现您的特定特征,然后装箱。不是最有效的,但它会起作用。

游乐场

也许我没有理解您试图表达的更深层次的问题,但从代码来看,它没有编译的原因是因为函数fn new_specific_box() -> Box<dyn SpecificTrait>的返回类型是Box<dyn SpecificTrait>,正如您所期望的Box<dyn GeneralTrait>。这两种类型不同,因此此代码不会编译。如果您可以匹配类型,那么编译应该是可以的。

相关内容

  • 没有找到相关文章

最新更新