[英]Instantiating a struct parameterized by a trait
我正在Rust中构建一个webapp,并尝试实现基本的Rails风格的数据库迁移来管理我的数据库。 在我的代码, Migration
是与性状up
和down
的方法来应用和回滚迁移。 每个单独的数据库迁移都是实现迁移特征的结构。 为了以正确的顺序跟踪数据库迁移,我构建了一个MigrationIndex
类。
struct MigrationIndex<T> {
migrations: Vec<Box<T>>
}
impl <T: Migration> MigrationIndex<T> {
// methods for managing the migrations...
}
impl <T: Migration> Default for MigrationIndex<T> {
pub fn default() -> MigrationIndex<T> {
MigrationIndex {
migrations: vec![]
}
}
}
所以我去上课:
let migrations: MigrationIndex = Default::default();
但是这行上的编译错误wrong number of type arguments: expected 1, found 0
。 所以我尝试添加缺少的特征参数:
let migrations: MigrationIndex<Migration> = Default::default();
但是在那一行上,编译器将Migration解释为一种类型,而不是一种特征,并且再次无法编译。 猜测我试过了:
let migrations: MigrationIndex<T: Migration> = Default::default();
但最终会出现语法错误。 现在我很难过。 如果某个类型由特征参数化,那么在实例化时如何指定该特征?
为泛型类型参数指定值时,它必须是具体类型,而不是特征:
trait Migration {}
struct Foo;
impl Migration for Foo {}
fn main() {
let migrations: MigrationIndex<Foo> = Default::default();
}
使用泛型时,泛型参数必须是单个具体类型。 这将导致迁移Vec
中的所有对象具有相同的类型。 根据你的描述,这听起来并不像你想要的那样。 您想要一个实现相同特征的不同类型的Vec
。 这不需要泛型:
#[derive(Default)]
struct MigrationIndex {
migrations: Vec<Box<Migration>>
}
impl MigrationIndex {
// methods for managing the migrations...
}
我还冒昧地通过derive
属性用等效的自动生成的替换你的手动Default
impl。
实际上,在您之前的实现中, Box
完全没有必要。 如果您具有具体类型,则可以直接创建该类型的Vec
元素。 只有当你想要放入实现相同特征的不同类型时才需要Box
,因为这些类型可能有不同的大小。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.