rust - 除非我使用临时变量,否则为什么我不能插入 Vec 的 dyn Trait?

标签 rust polymorphism traits parametric-polymorphism trait-objects

这是我的代码:

use std::rc::{Rc, Weak};
use std::cell::RefCell;

trait Trait {}

fn push<E: Trait>(e: E) {
    let mut v: Vec<Rc<RefCell<Box<dyn Trait>>>> = Vec::new();
    
    // let x = Rc::new(RefCell::new(Box::new(e)));
    // v.push(x); // error

    v.push(Rc::new(RefCell::new(Box::new(e)))); // works fine
}
v.push(x)引发此错误:
error[E0308]: mismatched types
  --> src/main.rs:12:12
   |
7  | fn push<E: Trait>(e: E) {
   |         - this type parameter
...
12 |     v.push(x);
   |            ^ expected trait object `dyn Trait`, found type parameter `E`
   |
   = note: expected struct `std::rc::Rc<std::cell::RefCell<std::boxed::Box<dyn Trait>>>`
              found struct `std::rc::Rc<std::cell::RefCell<std::boxed::Box<E>>>`
但是,如果我将值(用完全相同的值和类型构造)直接推送到向量中,它会编译而不会出错。
那么为什么第一个版本不编译呢?我应该改变什么才能使用 x在将其插入向量之前?

最佳答案

这一切都在类型推断中。当你写:

v.push(Rc::new(RefCell::new(Box::new(e))));

Rust 可以从该上下文中看出 RefCell::new() 的参数必须是 Box<dyn Trait> , 所以尽管提供了 Box<E> ,它将它强制转换为前一种类型。另一方面,当您编写此代码时:

let x = Rc::new(RefCell::new(Box::new(e)));
v.push(x); // compile error

Rust 首先推断 x类型 Rc<RefCell<Box<E>>>你不能再push它变成了vecRc<RefCell<Box<dyn Trait>>> .您可以通过在 let 中添加显式类型注释来更改它。绑定(bind)来预先告诉 Rust 你真的想要一个 Rc<RefCell<Box<dyn Trait>>> :

use std::rc::{Rc, Weak};
use std::cell::RefCell;

trait Trait {}

fn push<E: Trait>(e: E) {
    let mut v: Vec<Rc<RefCell<Box<dyn Trait>>>> = Vec::new();

    let x: Rc<RefCell<Box<dyn Trait>>> = Rc::new(RefCell::new(Box::new(e)));
    v.push(x); // compiles
}

playground

这里要理解的重要一点是 Edyn Trait 不一样. ETrait 的一些已知的具体实现而dyn Trait是一个特征对象,其底层的具体实现已被删除。

关于rust - 除非我使用临时变量,否则为什么我不能插入 Vec 的 dyn Trait?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61972343/

相关文章:

enums - Rust:将借用的结构传递给借用的枚举?

iterator - Rust 检查迭代器 : cannot borrow `*` as immutable because it is also borrowed as mutable

stream - 如何为 futures::Stream 编写 len 方法?

python - 概括类方法,根据条件执行略有不同的操作

oop - 从字符串动态创建选择器

rust - 在特征实现的上下文中理解 'self' 参数

collections - 如何通过获取可变变量的所有权来替换它的值?

polymorphism - "Polymorphism is not the same as method overloading or method overriding."

c++ - 如何为 operator<< 创建 C++ 模板

rust - 为什么不能将盒装结构作为特征借用?