trait可以有默认实现,这样可以做到类似template method的设计模式,例如

    1. trait Stores<TModel> {
    2. fn get_by_id(&self, id: u64) -> TModel;
    3. }
    4. trait Storage {
    5. fn query<TModel>(&self, id: u64) -> TModel
    6. where
    7. Self: Stores<TModel> // Self constrain
    8. {
    9. self.get_by_id(id)
    10. }
    11. }
    12. struct UserDatabase {}
    13. impl Storage for UserDatabase {}

    当UserDatabase实现了Storage这个trait后,就有了query的能力,这里可以看到where约束除了可以约束泛型类型T外,还能约束 Self 这里约束了Self必须实现 Stores<TModel>, 这样在query方法中就能调用Stores 的方法,我们就能为每种类型的实现get_by_id这个方法

    1. impl Stores<User> for UserDatabase {
    2. fn get_by_id(&self, id: u64) -> User {
    3. User{id: 123}
    4. }
    5. }
    6. impl <'a> Stores<Avatar<'a>> for UserDatabase {
    7. fn get_by_id(&self, id: u64) -> Avatar<'a> {
    8. Avatar{id: 123, url: url}
    9. }
    10. }
    11. #[derive(Debug)]
    12. struct User {
    13. id: u64,
    14. }
    15. #[derive(Debug)]
    16. struct Avatar<'a> {
    17. id: u64,
    18. url: &'a str,
    19. }
    1. fn main() {
    2. let db = UserDatabase{};
    3. let u = db.query::<User>(1);
    4. println!("user is {:?}", u);
    5. let a = db.query::<Avatar>(2);
    6. println!("Avatar is {:?}", a);
    7. }