Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Definition of traits in a separate file

Tags:

I define two structs

pub struct Rect {
    pub width:  f32,
    pub length: f32
}

//and

pub struct Circle {
    pub radius:  f32
}

Then I define a trait Area and I implement this trait for both Circle and Rect. Everything works fine when I put all source code in a single main.rs file.

Now I want to organize my source code. In particular, I want to create a folder /src/geometry, create three rs files under that folder:

// /src/geometry/rect.rs
pub struct Rect {
    pub width:  f32,
    pub length: f32
}
// /src/geometry/circle.rs
pub struct Circle {
    pub radius:  f32
}

and

// /src/geometry/traits.rs
pub trait Area {
    fn area(&self) -> f32;
}

And finally I want to use these structs from main.rs.

I spent a couple of days, read through all examples I found on the Internet, but I still can't get it to work. Any suggestions?

UPDATE: Project structure:

src
  geometry
     rect.rs 
     circle.rs
     traits.rs
  geometry.rs
  main.rs
// rect.rs

pub struct Rect {
    pub width:  f32,
    pub length: f32
}

impl Area for Rect {
    fn area(&self) -> f32 {
        self.width * self.length
    }
}

impl Perimeter for Rect {
    fn perimeter(&self) -> f32 {
        2.0*(self.width + self.length)
    }
}
// circle.rs

pub struct Circle {
    pub radius:  f32
}

impl Area for Circle {
    fn area(&self) -> f32 {
        3.14*self.radius*self.radius
    }
}

impl Perimeter for Circle {
    fn perimeter(&self) -> f32 {
        2.0*3.14*self.radius
    }
}
// traits.rs

pub trait Perimeter {
    fn perimeter(&self) -> f32;
}

pub trait Area {
    fn area(&self) -> f32;
}
// geometry.rs
pub mod rect;
pub mod circle;
// main.rs

mod geometry;
use geometry::rect::Rect;
use geometry::circle::Circle;

fn main() {
     let rect = Rect{ width: 1.0, length: 2.0 };
     let circle = Circle{ radius: 2.3 };

     println!("{}", rect.area());
     println!("{}", circle.area());
}

COMPILER ERROR MSGS

error[E0405]: cannot find trait `Area` in this scope
 --> src/geometry/rect.rs:6:6
  |
6 | impl Area for Rect {
  |      ^^^^ not found in this scope

error[E0405]: cannot find trait `Perimeter` in this scope
  --> src/geometry/rect.rs:12:6
   |
12 | impl Perimeter for Rect {
   |      ^^^^^^^^^ not found in this scope

error[E0405]: cannot find trait `Area` in this scope
 --> src/geometry/circle.rs:5:6
  |
5 | impl Area for Circle {
  |      ^^^^ not found in this scope

error[E0405]: cannot find trait `Perimeter` in this scope
  --> src/geometry/circle.rs:11:6
   |
11 | impl Perimeter for Circle {
   |      ^^^^^^^^^ not found in this scope

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0405`.
error: could not compile `chapter10`.
like image 835
HardFork Avatar asked Jul 18 '20 06:07

HardFork


1 Answers

First of all, in circle.rs and rect.rs you need to add use crate::geometry::traits::{Area, Perimeter};: this takes care of the errors you pasted.

Then, in main.rs you need to use geometry::traits::Area; otherwise you can't call .area() method. In order to do that, you need to make the traits module public in geometry.rs: pub mod traits; (or at least public within the crate: pub(crate) mod traits;).

Personally, I would also rename geometry.rs to geometry/mod.rs.

like image 162
lbolla Avatar answered Sep 30 '22 01:09

lbolla