I am trying to write a 3d application in rust and since I don't know any suitable alternatives I am currently "approximating" some java like classes using enums.
What I have looks something like this:
enum SceneObj {
Plane(Plane),
Sphere(Sphere),
}
Where Plane
and Sphere
are both structs. The this is necessary since I want to sore a vec of scene objects.
The problem now arises when I try to, for example, get the position of one of these scene objects. I always have to do something like this:
fn get_scobj_pos(obj: SceneObj) -> Vector {
match obj {
SceneObj::Plane(p) => { p.get_pos() }
SceneObj::Sphere(s) => { s.get_pos() }
}
}
This is really annoying and gets very verbose quickly. It also seems very redundant since all scene objects implement the same trait with these functions.
If I was using a language like Java, C# etc. I could just make the parent class Object and have Plane and Sphere inherit from it.
My question essentially boils down to: is there an alternative solution other than enums. More esoteric alternatives to OOP in 3d programming are also very welcome.
CodePudding user response:
You may want to create a trait SceneObj
, then use Box<dyn SceneObj>
if you plan on owning and storing the objects.
Traits are similar to interfaces in Java.
trait SceneObj {
fn get_pos(&self) -> &Vector;
}
struct Plane {
pos: Vector
}
impl SceneObj for Plane { //~ class Plane implements SceneObj
fn get_pos(&self) -> &Vector { //~ @Override Vector getPos()
&self.pos
}
}
But you should avoid using Box<dyn Trait>
carelessly.
CodePudding user response:
Prefer composition over inheritance, then use helper traits to access different parts of your composed objects more easily. In your case you could do something like:
struct Vector {}
struct BaseObject {
pos: Vector,
}
trait AsBaseObject {
fn as_base_object (&self) -> &BaseObject;
fn get_pos (&self) -> &Vector {
&self.as_base_object().pos
}
}
impl AsBaseObject for BaseObject {
fn as_base_object (&self) -> &BaseObject { self }
}
struct Plane {
base: BaseObject,
}
impl AsBaseObject for Plane {
fn as_base_object (&self) -> &BaseObject {
&self.base
}
}
struct Sphere {
base: BaseObject,
}
impl AsBaseObject for Sphere {
fn as_base_object (&self) -> &BaseObject {
&self.base
}
}
CodePudding user response:
Thank you to @ImajinDevon their awnser was very helpful. Here a quick implementation on the rust playground: rust playground