问题描述
试图创建一个数据库结构,它是向量的 HashMap
.每个Vec
包含Box
.
Trying to create a DB struct that is a HashMap
of vectors. Each Vec
contains 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
?
Why can't the compiler infer that User
and Message
implement Model
?
推荐答案
Box
和 Box
类型不可互换.即使使用不安全的代码,包含一个的集合也不能直接转换为另一个.这些类型是不同的,并且在内存中有不同的表示.它们甚至有不同的尺寸:
The types Box<dyn Model>
and Box<User>
are not interchangeable. Collections containing one cannot be directly transformed into the other, even with unsafe code. These types are different and have different representations in memory. They even have different sizes:
println!("{}", std::mem::size_of::<Box<User>>()); // 8
println!("{}", std::mem::size_of::<Box<dyn Model>>()); // 16
从 Vec
转换为 Vec
的唯一方法是逐项转换.每个项目都需要像这样被强制:
The only way to convert from Vec<Box<User>>
to Vec<Box<dyn Model>>
is on an item-by-item basis. Each item needs to be coerced like this:
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()
);
如果您在此之后不需要原始向量,则可以通过使其可变和排空来避免克隆:
If you don't need the original vector after this, you avoid cloning by making it mutable and draining instead:
tables.insert(
"users".to_string(),
users
.drain(..)
.map(|user| Box::<dyn Model>::from(user))
.collect(),
);
这篇关于如何将结构的 Vec 强制转换为特征对象的 Vec?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!