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

时间:2015-08-21 01:10:37

标签: rust

我在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();

但最终会出现语法错误。现在我很难过。如果某个类型是由特征参数化的,那么在实例化它时如何指定该特征呢?

2 个答案:

答案 0 :(得分:3)

为泛型类型参数指定值时,它必须是具体类型,而不是特征:

trait Migration {}

struct Foo;
impl Migration for Foo {}

fn main() {
    let migrations: MigrationIndex<Foo> = Default::default();
}

答案 1 :(得分:3)

使用泛型时,泛型参数必须是单一的具体类型。这将导致迁移Vec中的所有对象属于同一类型。根据你的描述,这听起来并不像你想要的那样。您需要实现相同特征的Vec个不同类型。这不需要泛型:

#[derive(Default)]
struct MigrationIndex {
    migrations: Vec<Box<Migration>>
}
impl MigrationIndex {
    // methods for managing the migrations...
}

我还冒昧地用Default属性替换您的手册derive impl与等效的自动生成的。{/ p>

事实上,在您之前的实施中,Box完全没必要。如果您具有具体类型,则可以直接创建该类型的Vec个元素。只有当您想要实现相同特征的不同类型时才需要Box,因为这些类型可能有不同的大小。