#Traits, problem with vec<box<trait>>

60 messages · Page 1 of 1 (latest)

orchid radish
#

So i'm trying to take a ppdl domain and write him in rust
My problem is a Grid HorizontalCar HorizontalTruck VerticalCar VerticalTruck each one of them is a struct
This is the traits i have in my projects -

pub trait Vehicle {
    fn positions(&self) -> Vec<(usize, usize)>; // Get occupied positions
    fn name(&self) -> &str; // Get the object's name
    fn as_any(&self) -> &dyn Any; // Enables downcasting
}

pub trait HorizontalVehicle: Vehicle {
    fn move_left(&mut self, grid: &mut Grid) -> Result<String, String>;
    fn move_right(&mut self, grid: &mut Grid) -> Result<String, String>;
}

pub trait VerticalVehicle: Vehicle {
    fn move_up(&mut self, grid: &mut Grid) -> Result<String, String>;
    fn move_down(&mut self, grid: &mut Grid) -> Result<String, String>;
}```


so i have impl in the each struct for Vehicle and to Verical\horizontalVehicle depend on what he his 
All the logic working well 
My problem is now i want to create a generate_moves that possible from a grid ,
The function need to take the grid and make new grids by move each object 1 time and i get a new grid 

I have alot of problem with this because i'm trying to do OOP
```rust
pub objects: Vec<Box<dyn Vehicle>>,

this how i try to save the objects ...
and there is problem with the size and with the cloning can some one help me ? idc to share the project file

#

This is how struct look in my project


pub struct HorizontalCar {
    pub name: String,
    pub fixed_x: usize, 
    pub start_y: usize, 
}

impl fmt::Debug for HorizontalCar {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "HorizontalCar {{ name: {}, fixed_x: {}, start_y: {} }}",
            self.name, self.fixed_x, self.start_y
        )
    }
}

impl HorizontalCar {
  
    pub fn new(fixed_x: usize, start_y: usize, name: String) -> Self {
        Self {
            name,
            fixed_x,
            start_y,
        }
    }
}

impl Vehicle for HorizontalCar {
    fn positions(&self) -> Vec<(usize, usize)> {
        vec![
            (self.fixed_x, self.start_y),
            (self.fixed_x, self.start_y + 1),
        ]
    }

    fn name(&self) -> &str {
        &self.name
    }

    fn as_any(&self) -> &dyn Any {
        self
    }
}

impl HorizontalVehicle for HorizontalCar {
    fn move_left(&mut self, grid: &mut Grid) -> Result<String, String> {
        if self.start_y == 0 || grid.cells[self.fixed_x][self.start_y - 1].is_some() {
            return Err("Cannot move left: Cell is occupied or out of bounds.".to_string());
        }

        
        grid.cells[self.fixed_x][self.start_y + 1] = None;

        
        self.start_y -= 1;

        grid.cells[self.fixed_x][self.start_y] = Some(self.name.clone());

        Ok(format!("{} moved left", self.name))
    }

    fn move_right(&mut self, grid: &mut Grid) -> Result<String, String> {
      
        if self.start_y + 2 == grid.col_size || grid.cells[self.fixed_x][self.start_y + 2].is_some()
        {
            return Err("Cannot move right: Cell is occupied or out of bounds.".to_string());
        }

       
        grid.cells[self.fixed_x][self.start_y] = None;
       
        self.start_y += 1;

        grid.cells[self.fixed_x][self.start_y + 1] = Some(self.name.clone());

        Ok(format!("{} moved right", self.name))
    }
}

abstract holly
#

For this type of problem domain, where you have a particular set of game pieces, you should use an enum of them instead of a trait and dyn.

orchid radish
abstract holly
#
struct Vehicle {
    kind: VehicleKind,
    position: [usize; 2],
}
enum VehicleKind {
    HorizontalCar,
    HorizontalTruck,
    VerticalCar,
    VerticalTruck,
}
orchid radish
#

i just want to add struct of object and i'm dont i cant do this in rust ?

abstract holly
#

you “just” add a variant to the enum

orchid radish
#

So what you trying to say rust it's not OOP like java and c# and other languages

abstract holly
#

this is almost the same amount of code; it is organized differently.

#

“Rust is not OOP” is a really broad statement, which is both true in many ways and false in some ways.

orchid radish
#

why you did the Vehicle as struct ?

abstract holly
#

Rust does use method dispatch and encapsulation.
Rust doesn't use inheritance.

abstract holly
#

the alternative would be putting it inside each enum variant, but that leads to more repeated code, so it is usually undesirable (but possible)

orchid radish
#

You have a place to give me where i can read about enum and more things about rust ?

#

Like my problem now that i try to write the domain that i wrote in rust

abstract holly
#

anyway, once you have simple data structures like this, you can just #[derive(Clone)] on them and you don't have any of the problems that come with trait objects

orchid radish
#

that what i tried to do

#

so Not to use Traits ?

abstract holly
#

sorry, I don't have any recommendations for tutorials — I'm a “start with the reference manual” kind of very long experienced programmer

abstract holly
# orchid radish so Not to use Traits ?

traits have their place. in particular, if you were writing some “game board” management code that is generic over different games — not different pieces in a game — a trait Piece might well make sense

#

there are also many places where dyn makes sense

#

it just happens that this one is not one of them

orchid radish
#

Ye true

#

So wait can i ask a question ?

#

if i have 4 objects each one of them work diffrent in position and in move function
it's better to create 4 objects no ?

#

4structs*

abstract holly
#

You can make dyn Vehicle work; it is just not a good plan. In particular, you could make it clonable-ish by using Rc<dyn Vehicle> instead of Box<dyn Vehicle>. But I strongly recommend you don't do that for this particular problem.

#

no, I actually don't think it is better

#

this is because all of these 4 things are in fact very similar. they all do the same kind of thing, just with different directions and different sizes

orchid radish
#

i'm gonna hear you boss you helping me alot

orchid radish
abstract holly
#

the differences between HorizontalCar HorizontalTruck VerticalCar VerticalTruck can and should be described more as data than as code

orchid radish
#

data you mean by explain you the problem ?

#

each car too 2 cells , truck 3 cells
i have a grid of nXm and the problem is to move the red-car where is have in each game to a place that i will call him goal .

#

when you horizontal you have same y if you a car you place in x,y x+1,y
i f you vertical you have the same x if you a truck you place in x,y x+1.y x+2,y

#

And sorry for my english 😦 i'm not the best

abstract holly
#

I might start with something like this:

#[derive(Clone, Copy)]
enum VehicleKind {
    HorizontalCar,
    HorizontalTruck,
    VerticalCar,
    VerticalTruck,
}
impl VehicleKind {
    fn length(self) -> usize {
        match self {
            Self::HorizontalCar => 2,
            Self::VerticalCar => 2,
            Self::HorizontalTruck => 3,
            Self::VerticalTruck => 3,
        }
    }
    fn direction(self) -> Direction {
        match self {
            Self::HorizontalCar => Direction::Horizontal,
            Self::VerticalCar => Direction::Vertical,
            Self::HorizontalTruck => Direction::Horizontal,
            Self::VerticalTruck => Direction::Vertical,
        }
    }
}
orchid radish
#

and how i create a Vehicle by the enum ?

#

by the way it's look like lamda expression or like ocaml

abstract holly
#
let vehicle = Vehicle {
    kind: VehicleKind::Vertical,
    position: [0, 0],
};
orchid radish
#

Vehicle from where this came

abstract holly
#

I wrote struct Vehicle earlier

orchid radish
#
struct Vehicle {
    kind: VehicleKind,
    position: [usize; 2],
}
#

you right but there is a problem with this struct

#

because the postion cant be only for 2

abstract holly
#

? it has a horizontal position and a vertical position

#

if you like you can use two fields, it's the same

#

; 2 there means "array of 2 elements"

#

like a 2d vector/point

orchid radish
#
struct Vehicle{
kind: VehicleKind,
position[can be 3/2 if it's truck it's 3]
direction: [usize;1] we can say 1 it's Horizontal { or better to sayString} ? 
}
#

now How i create each move function to each kind of Vehicle ?

abstract holly
#

you would write one move function that consults kind.length() and kind.direction() to figure out how it moves

#

this is better code organization because it means you are less likely to have a bug that affect one type of vehicle and not the others

orchid radish
#

ooo ok istart to understand you

#

wow brother!!!

#
if kind.direction()== Vertical
up , down depents on len 
same for horizontal
#

How i solve the position in Vehicle struct ?

#

Better to write 2 strucks 1 for car and 1 for truck ?