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?
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