尝试创建一个HashMap
向量的DB结构。每个Vec
包含Box<dyn Model>
。
use std::collections::HashMap;
trait Model {
fn id(&self) -> i32;
}
struct User;
struct Message;
impl Model for User {
fn id(&self) -> i32 { 4 }
}
impl Model for Message {
fn id(&self) -> i32 { 3 }
}
struct DB {
users: Vec<Box<User>>,
messages: Vec<Box<Message>>,
tables: HashMap<String, Vec<Box<dyn Model>>>,
}
impl DB {
fn new() -> Self {
let users: Vec<Box<User>> = Vec::new();
let messages: Vec<Box<Message>> = Vec::new();
let mut tables: HashMap<String, Vec<Box<dyn Model>>> = HashMap::new();
tables.insert("users".to_string(), users);
tables.insert("messages".to_string(), messages);
Self {
users,
messages,
tables,
}
}
}
编译器会产生以下错误:
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/lib.rs:37:44
|
37 | tables.insert("users".to_string(), users);
| ^^^^^ expected trait Model, found struct `User`
|
= note: expected type `std::vec::Vec<std::boxed::Box<dyn Model>>`
found type `std::vec::Vec<std::boxed::Box<User>>`
error[E0308]: mismatched types
--> src/lib.rs:38:47
|
38 | tables.insert("messages".to_string(), messages);
| ^^^^^^^^ expected trait Model, found struct `Message`
|
= note: expected type `std::vec::Vec<std::boxed::Box<dyn Model>>`
found type `std::vec::Vec<std::boxed::Box<Message>>`
为什么编译器不能推断User
和Message
实现Model
?
答案 0 :(得分:3)
类型Box<dyn Model>
和Box<User>
不可互换。即使使用不安全的代码,包含一个的集合也不能直接转换为另一个。这些类型不同,并且在内存中具有不同的表示形式。它们甚至有不同的大小:
println!("{}", std::mem::size_of::<Box<User>>()); // 8
println!("{}", std::mem::size_of::<Box<dyn Model>>()); // 16
从Vec<Box<User>>
到Vec<Box<dyn Model>>
转换的唯一方法是逐项进行。每个项目都需要像这样强制:
let model: Box<dyn Model> = user;
或者:
let model = Box::<dyn Model>::from(user);
导致这种丑陋的事情:
tables.insert(
"users".to_string(),
users
.iter()
.map(|user| Box::<dyn Model>::from(user))
.collect()
);
如果此后不需要原始向量,则可以通过使其可变并耗尽来避免克隆:
tables.insert(
"users".to_string(),
users
.drain(..)
.map(|user| Box::<dyn Model>::from(user))
.collect(),
);