Home > Blockchain >  OOP is discouraged in Rust but there don't seem to be a lot of alternatives for it in 3d applic
OOP is discouraged in Rust but there don't seem to be a lot of alternatives for it in 3d applic

Time:07-29

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
    }
}

Playground

CodePudding user response:

Thank you to @ImajinDevon their awnser was very helpful. Here a quick implementation on the rust playground: rust playground

  • Related