到目前为止,我很少遇到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>
。这两种类型不同,因此此代码不会编译。如果您可以匹配类型,那么编译应该是可以的。