如何使我自己的适配器方法能够使用特征对象?

时间:2015-06-04 02:12:41

标签: rust traits

我有一个具有"适配器方法的特性"使用方法:

struct Bar<T>(T);

trait Foo {
    fn make_bar(self) -> Bar<Self>
    where
        Self: Sized,
    {
        Bar(self)
    }
}

impl Foo for u8 {}
impl Foo for bool {}

这是在Iterator之后建模的。当我使用Box<Iterator>时,我仍然可以调用Iteratormapfilter适配器方法:

fn main() {
    let a = vec![1, 2, 3];
    let b: Box<Iterator<Item = u8>> = Box::new(a.into_iter());
    let c = b.map(|x| x * 2);
    for z in c {
        println!("{}", z)
    }
}

然而,我所定义的方法并没有以同样的方式运作:

fn main() {
    let a: Box<Foo> = Box::new(42);
    a.make_bar();
}

失败并显示错误

error[E0277]: the trait bound `Foo: std::marker::Sized` is not satisfied
  --> src/main.rs:18:7
   |
18 |     a.make_bar();
   |       ^^^^^^^^ `Foo` does not have a constant size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `Foo`

绝对正确的是Foo没有大小 - 这是一个特质。但是,正如我所理解的,Box<Foo> 具有大小。什么是Iterator与我的代码不同的做法?

1 个答案:

答案 0 :(得分:6)

由于Iterator是对象安全的,因此特征对象Iterator实现了Iterator

由于impl<I: Iterator + ?Sized> Iterator for Box<I>,盒装特征对象Box<Iterator>会实现Iterator

因此,在您的情况下,解决方案是为Foo实施Box<Foo>。这可能是通用的,如Iteratorimpl<T: ?Sized + Foo> Foo for Box<T> { }),也可能是特定的(impl Foo for Box<Foo> { })。