我问了一个类似的question earlier,它帮助我理解了幕后发生的事情但是我仍然无法让Rust做我希望它做的事情。通用编程。这是一些代码:
struct Foo<B: Bar> { bars: Vec<Box<B>> }
struct Foo2;
trait Bar {}
impl Bar for Foo2 {}
impl<B: Bar> Foo<B> {
fn do_something() -> Foo<B> {
let foo2:Box<Bar> = box Foo2;
let mut foo = Foo { bars: vec!(box Foo2) };
foo.bars.push(box Foo2);
foo // compiler: *ERROR*
}
}
错误:expected 'Foo<B>', found 'Foo<Foo2>'
foo
(Foo
)实现Bar
(B: Bar
)? 版本:0.12.0-nightly (4d69696ff 2014-09-24 20:35:52 +0000)
我在@Levans的解决方案中看到的问题:
struct Foo2;
struct Foo3 {
a: int
}
trait Bar {
fn create_bar() -> Self;
}
impl Bar for Foo2 {
fn create_bar() -> Foo2 { Foo2 } // will work
}
impl Bar for Foo3 {
fn create_bar(a: int) -> Foo3 { Foo3 {a: a} } // will not work
}
错误:method 'create_bar' has 1 parameter but the declaration in trait 'Bar::create_bar' has 0
另外,我注意到了这一点:Bar::create_bar()
。 Rust会如何知道使用Foo2
的实现?
答案 0 :(得分:6)
使用<B: Bar>
定义函数时,您告诉编译器“您可以使用实现特征B
”的任何类型替换此函数Bar
。
例如,如果您创建了一个实现特征Foo3
的结构Bar
,编译器也可以调用do_something
B
为Foo3
,这对于您当前的实现是不可能的。
在您的情况下,您的do_something
函数会尝试创建一个B
对象,因此需要一种通用的方法来执行此操作,由Bar
特征给出,作为{{1}例如,方法如下:
create_bar()
回答编辑:
在你的代码中,它确实不会起作用,因为你希望将更多的参数传递给struct Foo<B: Bar> { bars: Vec<Box<B>> }
struct Foo2;
trait Bar {
fn create_bar() -> Self;
}
impl Bar for Foo2 {
fn create_bar() -> Foo2 { Foo2 }
}
impl<B: Bar> Foo<B> {
fn do_something() -> Foo<B> {
let mut foo = Foo { bars: vec!(box Bar::create_bar()) };
foo.bars.push(box Bar::create_bar());
foo
}
}
,这是不可能的,因为它不尊重create_bar
不接受任何参数的特征定义
但是这样的事情没有任何问题:
create_bar
关键是:你的struct Foo2;
struct Foo3 {
a: int
}
trait Bar {
fn create_bar() -> Self;
}
impl Bar for Foo2 {
fn create_bar() -> Foo2 { Foo2 }
}
impl Bar for Foo3 {
fn create_bar() -> Foo3 { Foo3 {a: Ou} }
}
函数无法创建do_something
对象而没有通用的方法,这种方式不依赖于Bar
中的哪种类型,前提是它实现了<B>
。这就是泛型的工作原理:如果你打电话给Bar
,就好像你在函数的整个定义中将do_something::<Foo2>()
替换为B
一样。
然而,我怀疑你真正要做的是存储不同类型,所有在同一个Vec中实现Foo2
,否则将一个Box包装在内部将是非常无用的,你可以使用trait对象实现这一点,并且它不需要泛型:
Bar
基本上,Trait对象是对象的引用或指针,被转换为Trait:
struct Foo<'a> { bars: Vec<Box<Bar + 'a>> }
struct Foo2;
trait Bar {}
impl Bar for Foo2 {}
impl<'a> Foo<'a> {
fn do_something() -> Foo<'a> {
let mut foo = Foo { bars: vec!(box Foo2 as Box<Bar>) };
foo.bars.push(box Foo2 as Box<Bar>);
foo
}
}
正如我的例子所示,它也适用于Boxes。