Reputation: 754
Just wondering how to put a trait with self into a vec? I thought it should be a common question but I have never searched the answer...
Here is the code:
use tokio::time::{delay_for, Duration};
#[async_trait::async_trait]
trait Interface: Default + Sized {
async fn update(&mut self) -> bool where Self: Sized;
}
struct Adder {
pub state: i32,
}
impl Default for Adder {
fn default() -> Self {
Self { state: 0 }
}
}
#[async_trait::async_trait]
impl Interface for Adder {
async fn update(&mut self) -> bool {
delay_for(Duration::from_millis(100)).await;
self.state = self.state + 1;
println!("Inc state to: {}", self.state);
return true;
}
}
struct Suber {
pub state: i32,
}
impl Default for Suber {
fn default() -> Self {
Self { state: 0 }
}
}
#[async_trait::async_trait]
impl Interface for Suber {
async fn update(&mut self) -> bool {
delay_for(Duration::from_millis(100)).await;
self.state = self.state - 1;
println!("Dec state to: {}", self.state);
return true;
}
}
fn main() {
let updaters: Vec<Box<dyn Interface>> = vec![Box::new(Adder::default()), Box::new(Suber::default())];
for mut u in updaters {
u.update();
}
}
But I will get the error:
error[E0038]: the trait `Interface` cannot be made into an object
--> src/main.rs:51:19
|
4 | trait Interface: Default + Sized {
| --------- ------- ----- ...because it requires `Self: Sized`
| | |
| | ...because it requires `Self: Sized`
| this trait cannot be made into an object...
...
51 | let updaters: Vec<Box<dyn Interface>> = vec![Box::new(Adder::default()), Box::new(Suber::default())];
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Interface` cannot be made into an object
Upvotes: 1
Views: 788
Reputation: 1526
This error occurs because the trait Interface
does not satisfy object safety.
- It must not require
Self: Sized
- All associated functions must either have a
where Self: Sized
bound, or
- Not have any type parameters (although lifetime parameters are allowed), and
- Be a method that does not use
Self
except in the type of the receiver.- It must not have any associated constants.
- All supertraits must also be object safe.
You can change trait Interface: Default + Sized
into trait Interface
(because Default
also requires Sized
). But I don't know if that meets your need. @UkonnRa
Upvotes: 2