trait可以有默认实现,这样可以做到类似template method的设计模式,例如
trait Stores<TModel> {
fn get_by_id(&self, id: u64) -> TModel;
}
trait Storage {
fn query<TModel>(&self, id: u64) -> TModel
where
Self: Stores<TModel> // Self constrain
{
self.get_by_id(id)
}
}
struct UserDatabase {}
impl Storage for UserDatabase {}
当UserDatabase实现了Storage这个trait后,就有了query的能力,这里可以看到where约束除了可以约束泛型类型T外,还能约束 Self
这里约束了Self必须实现 Stores<TModel>
, 这样在query方法中就能调用Stores 的方法,我们就能为每种类型的实现get_by_id这个方法
impl Stores<User> for UserDatabase {
fn get_by_id(&self, id: u64) -> User {
User{id: 123}
}
}
impl <'a> Stores<Avatar<'a>> for UserDatabase {
fn get_by_id(&self, id: u64) -> Avatar<'a> {
Avatar{id: 123, url: url}
}
}
#[derive(Debug)]
struct User {
id: u64,
}
#[derive(Debug)]
struct Avatar<'a> {
id: u64,
url: &'a str,
}
fn main() {
let db = UserDatabase{};
let u = db.query::<User>(1);
println!("user is {:?}", u);
let a = db.query::<Avatar>(2);
println!("Avatar is {:?}", a);
}