【问题标题】:traits and associated-types特征和相关类型
【发布时间】:2015-09-23 10:43:18
【问题描述】:

我正在尝试在 Rust 上实现一些带有特征和相关类型的东西。我不知道如何用文字来表达我的问题,所以我将添加一个代码 sn-p 来说明我正在尝试做的事情。

pub trait Person {}

pub trait Directory<P: Person> {
    type Per = P;
    fn get_person(&self) -> Self::Per;
}

pub trait Catalog {
    type Per : Person;
    type Dir : Directory<Self::Per>;

    fn get_directory(&self) -> Self::Dir;
}

fn do_something<C>(catalog: C) where C: Catalog {
    let directory : C::Dir = catalog.get_directory();

    // let person : C::Per = directory.get_person();
    // The code above fails with:
    //  error: mismatched types:
    //   expected `<C as Catalog>::Per`,
    //      found `<<C as Catalog>::Dir as Directory<<C as Catalog>::Per>>::Per`
    //   (expected trait `Catalog`,
    //       found trait `Directory`) [E0308]

    let person = directory.get_person();
    do_something_with_person(person);
}

fn do_something_with_person<P: Person>(p: P) {}

我希望上面的代码可以编译,但事实并非如此。

相反,我得到:

error: the trait `Person` is not implemented for the type `<<C as Catalog>::Dir as Directory<<C as Catalog>::Per>>::Per` [E0277]

其中,AFAICT,意味着编译器无法确定 person 变量具有 Person 特征。

我正在使用以下 rustc 版本:

rustc 1.2.0-dev (a19ed8ad1 2015-06-18)

我错过了什么吗?

【问题讨论】:

    标签: rust traits associated-types


    【解决方案1】:

    这里有更正:

    pub trait Directory<P: Person> {
        type Per : Person = P;
        fn get_person(&self) -> Self::Per;
    }
    

    Directory 中的类型 Per 可以在 trait 实现中重新定义。编译器不知道Self::Per(即实现中重新定义的Per)是否实现了特征Person,所以你必须绑定它来实现Person

    【讨论】:

      【解决方案2】:

      这是正确的代码:

      pub trait Person {}
      
      pub trait Directory {
          type Person: Person;
          fn get_person(&self) -> Self::Person;
      }
      
      pub trait Catalog {
          type Dir: Directory;
      
          fn get_directory(&self) -> Self::Dir;
      }
      
      fn do_something<C: Catalog>(catalog: C) {
          let directory = catalog.get_directory();
          let person = directory.get_person();
          do_something_with_person(person);
      }
      
      fn do_something_with_person<P: Person>(p: P) {}
      

      &lt;P: Person&gt; 是泛型语法。关联类型定义不使用泛型语法。

      一般来说全名;不要缩写它Per,留下它Person。它总是合格的(Directory::PersonC::Person&c.),所以没有歧义。 (Dir 是公认的 Directory 的缩写形式,所以我想两者都可以接受。不过,我可能倾向于使用 Directory。)

      也不需要在Catalog 上指定关联类型PersonSelf::Dir::Person 可以。

      【讨论】:

        猜你喜欢
        • 2011-11-19
        • 1970-01-01
        • 2018-03-11
        • 2013-01-26
        • 2022-07-05
        • 2022-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多