特征和关联类型
traits and associated-types
我正在尝试在 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)
我是不是漏掉了什么?
此处更正:
pub trait Directory<P: Person> {
type Per : Person = P;
fn get_person(&self) -> Self::Per;
}
Directory
中的类型 Per
可以在特征实现中重新定义。编译器不知道Self::Per
(即实现中重新定义的Per
)是否实现了trait Person
,所以你必须绑定它来实现Person
.
正确代码如下:
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
,保留 Person
。它总是合格的 (Directory::Person
, C::Person
, &c.),所以没有歧义。 (Dir
是 Directory
的公认缩写形式,所以我想两者都可以接受。不过,我可能倾向于使用 Directory
。)
也不需要在 Catalog
上指定关联类型 Person
; Self::Dir::Person
就行了。
我正在尝试在 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)
我是不是漏掉了什么?
此处更正:
pub trait Directory<P: Person> {
type Per : Person = P;
fn get_person(&self) -> Self::Per;
}
Directory
中的类型 Per
可以在特征实现中重新定义。编译器不知道Self::Per
(即实现中重新定义的Per
)是否实现了trait Person
,所以你必须绑定它来实现Person
.
正确代码如下:
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
,保留 Person
。它总是合格的 (Directory::Person
, C::Person
, &c.),所以没有歧义。 (Dir
是 Directory
的公认缩写形式,所以我想两者都可以接受。不过,我可能倾向于使用 Directory
。)
也不需要在 Catalog
上指定关联类型 Person
; Self::Dir::Person
就行了。