[英]How to coerce a Vec of structs to a Vec of trait objects?
尝试创建一个 DB 结构,它是向量的HashMap
。 每个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
?
Box<dyn Model>
和Box<User>
类型不可互换。 Collections 包含一个不能直接转换成另一个,即使是不安全的代码。 这些类型不同,在 memory 中有不同的表示。 它们甚至有不同的尺寸:
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(),
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.