我问过类似的早期问题已让我明白是怎么回事引擎盖下,但我仍然不能得到锈做我想做的事情,当谈到泛型编程.这是一些代码:
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*
}
}
Run Code Online (Sandbox Code Playgroud)
错误: expected 'Foo<B>', found 'Foo<Foo2>'
foo(Foo)implements 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
}
Run Code Online (Sandbox Code Playgroud)
错误: method 'create_bar' has 1 parameter but the declaration in trait 'Bar::create_bar' has 0
另外,我注意到了这一点:Bar::create_bar().Rust会如何知道使用它Foo2的实现?
当您使用<B: Bar>告诉编译器来定义函数时,"您可以B通过任何实现特征的类型替换此函数Bar".
例如,如果您创建一个结构Foo3实现特质Bar以及,编译器会期望能够调用do_something与B幸福Foo3,这是不可能与你当前的实现.
在你的情况下,你的do_something函数试图创建一个B对象,因此它需要一个通用的方法,由Bar特征给出,作为一个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
}
}
Run Code Online (Sandbox Code Playgroud)
回答编辑:
在你的代码中,它确实不会起作用,因为你希望传递更多的参数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} }
}
Run Code Online (Sandbox Code Playgroud)
关键是:如果没有通用的方法,你的do_something函数就无法创建Bar对象<B>,只要它实现,这种方式不依赖于哪种类型Bar.这就是泛型是如何工作的:如果你打电话do_something::<Foo2>(),这是完全一样,如果你换成B由Foo2你的函数的定义整.
然而,我怀疑你真正要做的是存储不同类型,所有都Bar在同一个Vec中实现,(否则将一个Box包装在内部将是非常无用的),你可以使用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
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,Trait对象是对象的引用或指针,被转换为Trait:
let foo2 = Foo2;
let bar = &foo2 as &Bar; // bar is a reference to a Trait object Bar
Run Code Online (Sandbox Code Playgroud)
正如我的例子所示,它也适用于Boxes.
| 归档时间: |
|
| 查看次数: |
423 次 |
| 最近记录: |