CodeBlanks Logo Icon CodeBlanks

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.

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

main.rs
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

main.rs
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&lt;dyn Ses&gt;</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

Question
let hayvanlar: Vec<____<dyn Ses>> = vec![Box::new(Kedi)];
Answer
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

All lessons in Advanced