将泛型中的 Box<T> 转换为 rust 中的 Box<dyn Trait>

问题描述 投票:0回答:2
如何将泛型中的Box转换为Box。


Container<Box<Dog>>

Container<Box<dyn Animal>>

//example fn main() { let container: Container<Box<Dog>> = Container(Box::new(Dog())); let test: Container<Box<dyn Animal>> = container; // expected struct `RcHash<Box<dyn Enity>>` // found struct `RcHash<Box<Role>>` let test = container as Container<Box<dyn Animal>>; // non-primitive cast: `Container<Box<Dog>>` as `Container<Box<dyn Animal>>` // an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object } //struct struct Container<T> (T); struct Dog (); //trait trait Animal { fn echo(&self); } impl Animal for Dog { fn echo(&self) { println!("dog"); } }
    
rust traits
2个回答
0
投票
您无法在

Box<Dog>Box<dyn Animal>

 之间进行简单的 
cast
,因为它们并不完全相同。两个 
Box
 都可以充当指向 
Dog
 实例的指针,但 
Box<dyn Animal>
 实际上将具有不同的 
size,因为特征对象还有一个额外的指针(对于 vtable)。我建议您阅读this以更好地理解有关特征对象的部分。

上述意味着你无法避免创建一个新的

Box<dyn Animal>

 实例,因此你无法避免创建一个新的 
Container<Box<dyn Animal>>
 实例(因为如果 
A != B
 => 
Container<A> != Container<B>
 /这里你可以将 
!=
 解释为“不兼容”或“不同的
尺寸”/)。

这是一个如何从

Box<dyn Animal>

 实例“手动”创建新 
Box<Dog>
 实例的示例:

let dog_box: Box<Dog> = Box::new(Dog()); let animal: Box<dyn Animal> = Box::new(*dog_box);
这基本上会

移动小狗实例(而不是创建另一个克隆)。

这是您的案例的更完整示例:

let container: Container<Box<Dog>> = Container(Box::new(Dog())); let cont_animal: Container<Box<dyn Animal>> = Container(Box::new(*container.0));
    

0
投票
这也许是一种更具可读性的方式,副驾驶刚刚建议,我还没有测试。

impl Trait for Something { fn foo() -> Vec<Box<dyn Info>> { let infos = json_parser .get_info::<BiliInfo>("")? // get_info need T to use serde_json .into_iter() .map(|i| Box::new(i) as Box<dyn Info>) .collect(); infos }}
我认为当特质要求我们这样做时我们就需要这样做。在这种情况下,trait 的方法 

foo

 需要 
infos
Box<dyn Info>
,但 serde_json 需要具体类型并且只能返回 
BiliInfo

定义特质时我们可以避免:

trait Trait { type Info: Info; fn foo() -> Self::Info; }
这样可以避免使用

Box

,但是由于我知识贫乏,不知道对性能或者其他方面的影响。

© www.soinside.com 2019 - 2024. All rights reserved.