我问了一个类似的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
)? -
这是一个错误吗?我应该推迟使用Rust直到它达到1.0?
版本: 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
的实现?
1 回答
当您使用
<B: Bar>
定义函数时,您告诉编译器“您可以在任何实现特征Bar
的类型中替换此函数B
” .例如,如果您创建了一个实现trait
Bar
的structFoo3
,那么编译器可以调用do_something
,B
为Foo3
,这对于您当前的实现是不可能的 .在您的情况下,您的
do_something
函数会尝试创建一个B
对象,因此它需要一个通用的方法来执行此操作,由Bar
trait给出,例如create_bar()
方法,如下所示:Answer to edit :
在你的代码中,它确实不会起作用,因为你希望将更多的参数传递给
create_bar
,这是不可能的,因为它不尊重create_bar
不接受任何参数的特征定义 .但是像这样的东西可以毫无问题地工作:
关键是:你的
do_something
函数无法创建Bar
对象而没有通用的方法,这种方式不依赖于<B>
中的哪种类型,只要它实现了Bar
. 这就是泛型如何工作:如果你调用do_something::<Foo2>()
,就好像你在函数的整个定义中用Foo2
替换了B
.然而,我怀疑你真正要做的是存储不同类型,所有在同一个Vec中实现
Bar
(否则将一个Box包装在内部将是非常无用的),你可以用特征对象实现这一点,并且它不需要泛型:基本上,Trait对象是对象的引用或指针,被转换为Trait:
正如我的例子所示,它也适用于Boxes .