在以下程序(play)中,FooBar
特征提供bar
方法,但bar
返回的对象的实际类型似乎是隐藏的。如果我使用类型参数而不是关联类型,它可以工作(play)。
为什么关联类型的处理方式不同?或者我做错了吗?
use std::ops::DerefMut;
pub trait FooBar: Sized {
type Assoc: Sized + DerefMut<Target=Self>;
fn foo(&mut self) -> Option<Self::Assoc>;
fn bar(mut this: Self::Assoc) -> Result<Self::Assoc, Self::Assoc> {
unimplemented!()
}
}
#[derive(Debug)]
struct Test(u32);
impl FooBar for Test {
type Assoc = Box<Test>;
fn foo(&mut self) -> Option<Self::Assoc> {
unimplemented!()
}
}
fn main() {
let mut tt = Test(20);
let tt_foo: Box<Test> = tt.foo().unwrap(); // this is ok
let tt_bar: Box<Test> = FooBar::bar(Box::new(tt)).unwrap(); // but not this
assert_eq!(tt_bar.0, 20);
}
答案 0 :(得分:4)
如果你的方法是
fn bar(mut this: Self::Assoc) -> Result<Self::Assoc, Self::Assoc>
你尝试用
调用它FooBar::bar(Box::new(tt))
Rust怎么知道Self
是什么类型的? Box::new(tt)
Self::Assoc
是正确的,但您无法从中获得Self
,有几种类型可能具有相同的Assoc
。
这就是rustc
抱怨的内容:
需要输入注释
您必须注释Self
的类型:
let tt_bar: Box<Test> = <Test as FooBar>::bar(Box::new(tt)).unwrap();
或等效地:
let tt_bar: Box<Test> = Test::bar(Box::new(tt)).unwrap();
答案 1 :(得分:1)
问题是您正在尝试从特征中访问关联的类型。您只能从实现特征的类型访问它,例如从Test
:
let tt_bar: Box<Test> = Test::bar(Box::new(tt)).unwrap();
FooBar::Assoc
不是具体类型,因此您无法使用它。当您为FooBar
实施Test
时,您为Test::Assoc
提供了一个具体类型,可以访问:
type Assoc = Box<Test>;
在具有泛型类型的代码中,使用具体类型创建了FooBar::bar
的新副本。因为您请求了Box<Test>
,所以新功能的签名将是:
fn bar(mut this: Box<Test>) -> Result<Box<Test>, Box<Test>>
Box<Test>
是一种具体的类型,所以它有效。