Rust
Box<dyn Trait>
Own a trait object with Box<dyn Trait>.
Box<dyn Trait>
Box<dyn Trait> is an owned trait object: the data lives on the heap, and when the box is dropped, the drop function in the vtable is called. It's the standard way to keep different types in one collection:
let hayvanlar: Vec<Box<dyn Ses>> = vec![Box::new(Kedi), Box::new(Kopek)];
for h in &hayvanlar {
println!("{}", h.ses());
}
It's also used to return different types from a function: fn yeni_hayvan(tur: &str) -> Box<dyn Ses>.
Factory function
Producing different types based on runtime information can't be done without trait objects:
fn yeni_hayvan(tur: &str) -> Option<Box<dyn Ses>> {
match tur {
"kedi" => Some(Box::new(Kedi)),
"kopek" => Some(Box::new(Kopek)),
_ => None,
}
}
Plugin systems, command tables and GUI component trees are built with this pattern.
Exercise Animal factory
Write the yeni_hayvan factory above. For ["kedi", "kopek", "kuş"], print the sounds of those created and tanınmadı for None.
Show example solution
trait Ses {
fn ses(&self) -> String;
}
struct Kedi;
struct Kopek;
impl Ses for Kedi {
fn ses(&self) -> String {
String::from("Miyav")
}
}
impl Ses for Kopek {
fn ses(&self) -> String {
String::from("Hav")
}
}
fn yeni_hayvan(tur: &str) -> Option<Box<dyn Ses>> {
match tur {
"kedi" => Some(Box::new(Kedi)),
"kopek" => Some(Box::new(Kopek)),
_ => None,
}
}
fn main() {
for t in ["kedi", "kopek", "kuş"] {
match yeni_hayvan(t) {
Some(h) => println!("{}", h.ses()),
None => println!("tanınmadı"),
}
}
}
Test yourself
-
If a <code>Box<dyn Ses></code> is to be sent to a thread, how should the type be written?
- Arc<dyn Ses>
- It can't be sent
- Box<dyn Ses + Send>
- Box<dyn Ses>
Show answer
Box<dyn Ses + Send> — A trait object carries only the traits it names; marker traits like Send are added explicitly.
-
Owned object
let hayvanlar: Vec<____<dyn Ses>> = vec![Box::new(Kedi)];
Show answer
let hayvanlar: Vec<Box<dyn Ses>> = vec![Box::new(Kedi)];
-
Type and property
- Box<dyn Ses>
- Owned
- &dyn Ses
- Borrowed
- Rc<dyn Ses>
- Shared
- Box<dyn Ses + Send>
- Sendable to threads
Next lesson: Static vs dynamic dispatch