rust - 创建 Box<dyn Trait> 时如何转换为 dyn Trait

标签 rust

在下面的代码中:

trait Animal {}
struct Dog {}
impl Animal for Dog {}
fn main() {
    // first two lines are OK as expected
    let _animal1: Box<dyn Animal> = Box::new(Dog {});
    let _animal2: Box<dyn Animal> = Box::new(Dog {}) as Box<dyn Animal>;
    // next line is a compile error: cast to unsized type: `Dog` as `dyn Animal`
    let _animal3: Box<dyn Animal> = Box::new(Dog {} as dyn Animal);
}

为什么将 Dog{} 转换为 dyn Animal 会出错?

对于此示例,编译器正确推断类型并且强制转换是多余的。然而,对于一般情况,应该使用什么来向编译器提供类型信息,而不是 dyn Animal

用不同的方式陈述问题:如果不是 dyn Animal,则赋予 Box::new() 的对象类型是什么?

最佳答案

我的理解是,对对象的每个引用(例如 &T&mut TBox<T>Arc<T> 等)都可以在不知道对象大小的情况下存在(例如满足Sized 特征)。示例中的前两行就是这种情况。

但是,在第三行中,您短暂地(在将其传递到 Box::new() 之前)将其转换为 dyn Animal ,它不是引用,而是一个对象。 Rust 中存在的每个对象都需要有一个已知的大小,否则 Rust 将不知道在堆栈上为其分配多少空间。这对于引用来说不是问题,因为引用具有独立于它们所引用的对象的恒定大小。

考虑一下:

let dog = Dog{};
// Works
let _animal : &dyn Animal = &dog as &dyn Animal;
// Fails
let _animal : dyn Animal = dog as dyn Animal;

我认为错误消息非常有解释性:

error[E0620]: cast to unsized type: `Dog` as `dyn Animal`
  --> src/main.rs:13:32
   |
13 |     let _animal : dyn Animal = dog as dyn Animal;
   |                                ^^^^^^^^^^^^^^^^^
   |
help: consider using a box or reference as appropriate
  --> src/main.rs:13:32
   |
13 |     let _animal : dyn Animal = dog as dyn Animal;
   |                                ^^^

For more information about this error, try `rustc --explain E0620`.

你问题的第二部分是“我应该用什么来把狗变成动物?”。

我的回答是:这取决于您是否想继承所有权。

如果您不想想要继承所有权并保留原始对象:

let dog = Dog{};
let animal: &dyn Animal = &dog;

否则,如果您想将所有权转移到动物对象中:

let dog = Dog{};
let animal: Box<dyn Animal> = Box::new(dog);

关于rust - 创建 Box<dyn Trait> 时如何转换为 dyn Trait,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72168734/

相关文章:

rust - 为什么我的 nom 解析器不消耗整个输入,而留下最后一 block 未解析?

reference - 有没有办法返回对函数中创建的变量的引用?

rust - 功能 'xxx' 依赖于 'yyy',这不是可选依赖项

rust - 解码存储在数据库中的数据

rust - 在 Rust 中,如何在向量的向量中合并两个子向量?

reference - 了解 Vec<T> 的调试实现

rust - 如何将 Future 作为函数参数传递?

closures - 从闭包填充集合时类型不匹配 "bound lifetime parameter"与 "concrete lifetime"

pointers - 什么是 "fat pointer"?

rust - 在 rust 1.26 及以后的版本中,如何将多个字符串写入一个文件而不让它们相互覆盖?