How to clone a struct storing a trait object?


#1

Hello everyone! :slight_smile:

I run into a problem when need to clone a struct that contains a trait object. Fortunately there is an answer on StackOwerflow that helped me (https://stackoverflow.com/a/30353928/5955876). But I still don’t understand the code. Could you please explain it to me piece by piece?
Thank you very much! :slight_smile:


#2

It’s a pretty good answer. Which parts don’t quite make sense?


#3

Why do we need this piece of code when Box already implements Clone trait (https://doc.rust-lang.org/std/boxed/struct.Box.html#impl-Clone):

impl Clone for Box<Animal> {
    fn clone(&self) -> Box<Animal> {
    self.clone_box()
    }
}

#4

Box<T> implements Clone if T implements Clone:

impl<T: Clone> Clone for Box<T>

Since Animal (the trait object type) does not implement Clone, this generic implementation does not apply.


#5

What is wrong with this code:

trait Animal: Clone {
    fn speak(&self);
}

#[derive(Clone)]
struct Dog {
    name: String,
}

impl Dog {
    fn new(name: &str) -> Dog {
        return Dog { name: name.to_string() }
    }
}

impl Animal for Dog {
    fn speak(&self) {
        println!("{}: ruff, ruff!", self.name);
    }
}

#[derive(Clone)]
struct AnimalHouse {
    animal: Box<Animal>,
}

fn main() {
    let house = AnimalHouse { animal: Box::new(Dog::new("Bobby")) };
    let house2 = house.clone();
    house2.animal.speak();
}

#6
trait Animal: Clone {
    fn speak(&self);
}

This says that the structure that implements Animal must also implement Clone. It does not add anything (Clone) for the “Trait Object” data type. (Trait Objects internal are an unsized type so can’t implement Clone.)
Nightly has addition of #![feature(dyn_trait)] (can try on play) that makes the case where your using a Trait Object more explicit.