0

这似乎是一个具体的问题,但我会尽量概括它。随意编辑标题,因为我是 Rust 新手,不知道如何简洁地表达它。

我想做的最好用例子来解释。

我正在使用柴油并生成schema.rs它定义了表格CatsDogs(使用table!宏)。

现在我为和(我实现的2个结构)编写了get_all函数CatDog

pub fn get_all_cats(connection: &PgConnection) -> Vec<Cat> {
    Cats
        .load::<Cat>(connection)
        .expect("Error")
}

pub fn get_all_dogs(connection: &PgConnection) -> Vec<Dog> {
    Dogs
        .load::<Dog>(connection)
        .expect("Error")
}

但由于他们基本上做同样的事情,我很想用一种get_all<T>方法来概括它们。

我想创造一个特征:

trait GetAll<T=Self> {
   fn get_all(conn: &PgConnection) -> Vec<T> {
      Resource.load::<T>(conn)
   }
}

当然,我Resource现在需要定义,要么是Cats要么Dogs。所以我想做一个解决方法并定义一个get_resource我可以覆盖的方法CatDog提供他们尊重的资源。这是类型diesel::query_dsl::RunQueryDsl<Conn>

问题是我不知道Conn必须实现什么类型约束(然后是该类型的类型参数,等等),我认为应该有一种更简单的方法,然后从柴油逆向工程整个类型链。

trait GetAll<T=Self> {
   fn get_resource() -> diesel::query_dsl::RunQueryDsl;

   fn get_all(conn: &PgConnection) -> Vec<T> {
      get_resource().load::<T>(conn)
   }
}

这失败了expected 1 type argument

我的方法是否有“修复”(例如编译器自动推断类型)或者设计是否损坏?如果是后者,我该如何概括该get_all方法?

PS:Queryabletrait 也是如此,它应该是 的约束T,但又需要 2 个类型参数。

4

1 回答 1

1

似乎您的特征需要关联类型。这使您可以表达数据结构具有与之关联的唯一资源类型的事实。

trait GetAll {
    type Resource; 
    fn get_all(conn: &PgConnection) -> Vec<Self> {
        Self::Resource::load::<Self>(conn)
    }
}

impl GetAll for Dog {
    type Resource = Dogs;
}

impl GetAll for Cat {
    type Resource = Cats;
}

您应该可以像这样使用它:

let dogs = Dog::get_all(&conn);
let cats = Cat::get_all(&conn);
于 2019-05-06T10:54:39.173 回答