Hello Rustaceans! I've been getting the feeling that I'm painting myself into a corner with a trait that I've written, I believe I've gotten in to trouble by thinking of traits as I would an "interface" in Java. Here is the trait in question (modified for brevity):
What I would like to do is have a Vec of structs that implement Shape (currently I have Sphere and Plane), and then be able to iterate over those things and call the intersections_with function on each of them given a single Ray. However, because the intersections_with function returns Vec<Intersection<Self>>, I'm not able to use dyn Shape.
At the moment, I'm at a loss as to how I should continue. Am I trying to go in a direction I shouldn't be, or am I missing something else going on here? I'm aiming to achieve some polymorphism here, which looks to be a fairly common stumbling point for Rust beginners—my apologies if it's too similar to other questions asked!
If you remove the Sized supertrait then you can return a Vec of Intersection<&dyn Shape>>. Whether that will hold up when you add more, I'm not sure, and maybe that's where the Java brain issue comes up.
What are you doing with the intersection? What do you need it for, and what methods does it have? The usefulness of returning typed or dynamic values depends crucially on thede details.
I'm going to try to give more context by answering a few questions raised so far. @quinedot and @paramagnetic you both asked questions about the Intersection, so to start, here is an abridged version that I hope gets to the utility of the Shape associated with it:
@quinedot your thought about the time value possibly being the only thing necessary did get me thinking, however because there are some other ways that I'm using the Shape (kind of confusingly referred to as object), I'd like to continue to have an Intersection that holds on to these other things.
@paramagnetic does that get to your questions as well? For more context, I'm working on building a ray tracing renderer, so my conception of the Intersection is that it represents a point on a ray that intersects some sort of shape (at the moment, a sphere or a plane). Elsewhere in the code, I use the Intersection to get more information on the intersected shape, specifically the "material" of it which is then used in the calculation of the color of a pixel. Hopefully that context is helpful!
Sorry @jumpnbrownweasel, I began experimenting with your suggestion but haven't had time yet today to get very far into it! I hope I'll be back with more questions later...
Hey everyone! Apologies for falling of off this, but I wanted to leave some sort of follow up because you all were very helpful, and in case this is helpful to anyone in the future. The solution that I ended up going with was to rewrite that intersections_with function on Shape to no longer return Intersections, but just a Vec of f64s that represent where the intersections occur on the given Ray—sorry I realize that that's all very specific to what I'm doing here, and not really useful knowledge.
However, a more interesting change that I made was to that Intersection, changing object from a generic type implementing Shape, to a Rc<dyn Shape>. This is really what I was trying to get at. The Rc<dyn Shape> does give me the polymorphism I was looking for, as well as some other properties that I couldn't achieve with a Box or Arc, although I'm having trouble piecing together the specifics of why those other two didn't work!
Again, thanks very much, and my apologies for not following up earlier!