我问了一个类似的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的实现?
发布于 2014-09-26 17:03:53
当您使用<B: Bar>定义函数时,您告诉编译器“您可以在此函数B中使用实现特征Bar的任何类型替换”。
例如,如果您还创建了一个struct Foo3实现特性Bar,那么编译器就可以使用B是Foo3调用do_something,这在当前实现中是不可能的。
在您的情况下,您的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 
  }
}编辑答案:
在您的代码中,它确实无法工作,因为您希望向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>(),就好像在函数的整个定义中用Foo2代替了B。
然而,我怀疑您真正想要做的是存储不同的类型,在同一个Vec中实现所有的Bar (否则将一个Box封装在里面将是非常无用的),您可以通过特性对象来实现这一点,并且它不需要泛型:
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
  }
}基本上,属性对象是对对象的引用或指针,作为属性进行转换:
let foo2 = Foo2;
let bar = &foo2 as &Bar; // bar is a reference to a Trait object Bar正如我的例子中所提供的,它也适用于盒子。
https://stackoverflow.com/questions/26063593
复制相似问题