繁体   English   中英

实例化由特征参数化的结构

[英]Instantiating a struct parameterized by a trait

我正在Rust中构建一个webapp,并尝试实现基本的Rails风格的数据库迁移来管理我的数据库。 在我的代码, Migration是与性状updown的方法来应用和回滚迁移。 每个单独的数据库迁移都是实现迁移特征的结构。 为了以正确的顺序跟踪数据库迁移,我构建了一个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM