特征和相关类型

时间:2015-07-06 10:16:45

标签: rust traits associated-types

我正在尝试使用traits和相关类型在Rust上实现一些东西。我不确定如何用文字形成我的问题,所以我将添加一个代码片段,希望能够说明我正在尝试做的事情。

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)

我错过了什么吗?

2 个答案:

答案 0 :(得分:5)

这里有更正:

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

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

答案 1 :(得分:4)

这是正确的代码:

user

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) {} 是泛型语法。关联类型定义不使用通用语法。

一般来说全名;不要将其缩写为<P: Person>,请保留Per。它始终是合格的(PersonDirectory::Person&amp; c。),所以没有歧义。 (C::PersonDir的公认缩写形式,所以我想其中任何一种都可以接受。但是,我可能倾向于使用Directory。)

也无需在Directory上指定关联类型Person; Catalog会这样做。