Help regarding polymorphism in Rust

I am trying to write a ray tracer in Rust, and my code lives here:

However, I have hit a roadblock on how to properly do dynamic dispatch and polymorphism.

In camera/, I have the base Trait that has two functions, new() and generate_camera_ray(), and a struct PinholeCamera that implements them. In src/, I parse the scene file and look for the camera type, and I need to call the corresponding Camera. I did look up the trait objects section of the book, however, I cannot get my code to compile. That brings me to have several questions:

  1. Is this the proper way to do dynamic dispatch? Most likely no, but a hint in the right direction would be highly appreciated.

  2. In src/, I have a match block that I use to construct the camera object, before storing it in SceneConfig. Is variable shadowing the idiomatic way to do this? (Since the camera object will not be living outside the match block…)

Any help would be appreciated!

Looking at your code, your problem has nothing to do with trait objects and dynamic dispatch.

  1. Rather than get fancy with the match statement, which initializes the camera exactly the same way in both branches, you can factor that out.
    a. (You also made a new binding for camera, which shadowed the old binding, this meant that you didn’t initialize the camera in all cases which led to the error later on that camera was possibly uninitialized).
  2. Then you can replace the match statement with an if, and print out the warning inside the if.
  3. You will also have to clone scene_filename, because you are using later after you move it.
1 Like

Thanks for the quick reply!

I pushed a few commits based on your feedback. Specifically, now I am initializing the Box pointer with:

let mut camera : Box<Camera> = Box::new(PinholeCamera::default());

So now I am initializing the Box with any one implementation of the trait Camera, and then shadowing it with the concrete object type which is determined later. Is this the idiomatic way?

A little sleep later, I realized that I didn’t need to initialize the base pointer. For whatever reason, I was under the impression that whenever I declare a variable, I have to assign it as well… But in this case just doing,

let mut camera : Box<Camera>;
match "typeOfCamera" {
 "a" => {camera = Box::new(Pinholecamera::new(...));},
_ => {}

would work just fine!

I guess this clears up my questions for now. Thanks a lot!