Box<dyn Trait>
- Rust course
- Advanced
- Lesson 55/81
- 4 min
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.
Practice Animal factory
Write the yeni_hayvan factory above. For ["kedi", "kopek", "kuş"], print the sounds of those created and tanınmadı for None.
Starter code
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 main() {
// buraya yaz
}Sample 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ı"),
}
}
}Expected output
Miyav Hav tanınmadı
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 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> Correct answer
- Box<dyn Ses>
Explanation: A trait object carries only the traits it names; marker traits like Send are added explicitly.
2 Owned object
let hayvanlar: Vec<____<dyn Ses>> = vec![Box::new(Kedi)];
let hayvanlar: Vec<Box<dyn Ses>> = vec![Box::new(Kedi)];
Explanation: Box<dyn Ses> owns the trait object.
3 Type and property
| Term | Meaning |
|---|---|
Box<dyn Ses> |
Owned |
&dyn Ses |
Borrowed |
Rc<dyn Ses> |
Shared |
Box<dyn Ses + Send> |
Sendable to threads |