2015-06-04 2 views
6

Ho un tratto che ha "metodi di adattamento", che consumano il metodo:Come faccio a rendere i miei propri metodi di adattatore in grado di consumare un oggetto tratto?

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 {} 

Questo è modellato Iterator. Quando uso una Box<Iterator>, posso ancora chiamare Iterator metodi di adattamento come map o filter:

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) 
    } 
} 

Tuttavia, i metodi ho definito non funzionano nello stesso modo:

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

Questo fallisce con gli errori

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` 

è assolutamente corretto che Foo non hai dimensioni - è un tratto. Tuttavia, Box<Foo>dovrebbe avere una dimensione, come ho capito,. Che cos'è Iterator facendo diversamente dal mio codice?

risposta

6

Poiché Iterator è protetto da oggetti, l'oggetto tratto Iterator implementa Iterator.

Perché impl<I: Iterator + ?Sized> Iterator for Box<I>, l'oggetto tratto box Box<Iterator> implementa Iterator.

Quindi nel tuo caso la soluzione è quella di implementare Foo per Box<Foo>. Questo potrebbe essere generico come Iterator (impl<T: ?Sized + Foo> Foo for Box<T> { }) o potrebbe essere specifico (impl Foo for Box<Foo> { }).

+0

Oh, 'impl MyTrait per Box ' - è molto più semplice di quanto mi aspettassi. Stavo guardando [fonte di 'Iterator'] (https://github.com/rust-lang/rust/blob/0aeb9f6f08c353c71d962d5cc7a231e73040ca3c/src/libcore/iter.rs) che non menzionava affatto 'Box'; Avrei dovuto invece guardare l'elenco di implementazione nei documenti :-) – Shepmaster