This is my first post about Rust, So I'm going to keep it simple and at the same time a bit unrealistic, just to prove some points. ;-)
This article, as the title already revealed, is all about operator overloading. Specifically we will implement the following 4 traits.
- PartialEq
- PartialOrd
- Add
- Not
Our example, as other similar tutorials will be based upon a little bit of Geometry, specifically Points and Lines.
so we need to use the following
use std::cmp::Ordering; use std::ops::Add; use std::ops::Not;
- a Point will be a pair of cartesian coordinates (x,y)
#[derive(Copy, Clone)] pub struct Point { pub x: f32, pub y: f32, }
- a Line will be a pair of Points
#[derive(Copy, Clone)] pub struct Line { pub start: Point, pub end: Point, }
- The Point trait will just have a constructor
pub trait PointProperties { fn new(x: f32, y: f32) -> Self; } impl PointProperties for Point { fn new(x: f32, y: f32) -> Self { return Self { x: x, y: y }; } }
- The Line trait will have a constructor and a function that calculates the length of the Line. The length is calculated with the distance formula ( √(b.x-a.x)^2 + (b.y-a.y)^2 ) that (I assume) we all know from school.
pub trait LineProperties { fn length(&self) -> f32; fn new(a: Point, b: Point) -> Self; } impl LineProperties for Line { fn length(&self) -> f32 { return ((&self.end.x - &self.start.x).powf(2.0) + (&self.end.y - &self.start.y).powf(2.0)) .sqrt(); } fn new(a: Point, b: Point) -> Self { return Self { start: a, end: b }; } }
First we will implement the equality. What is equality between two lines? In this case I am choosing to consider equal two lines that have the same length, regardless where they lie in our cartesian plane.
impl PartialEq for Line { fn eq(&self, other: &Self) -> bool { return &self.length() == &other.length(); } }
Then we have the less than and greater than symbols. Again how can we compare two lines? Again I am choosing to compare the lengths of two lines, again regardless where they line in our cartesian plane
impl PartialOrd for Line { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.length().partial_cmp(&other.length()) } }
Finally we down to the more unrealistic but handy nevertheless examples.
The not operator (!). In this case when applying the not operator in a line, flips the line along the y axis. This is achieved by simply reversing the signs of all cartesian coordinates that make up our line.
impl Not for Line { type Output = Line; fn not(mut self) -> Line { self.start.x = -self.start.x; self.start.y = -self.start.y; self.end.x = -self.end.x; self.end.y = -self.end.y; return self; } }
Finally I implement the add operator (+). Again adding two lines doesn't make much sense, so what I am doing with the add operator is that I take the min_x, min_y and max_x, max_y for each pair of coordinates (start vs end)
impl Add for Line { type Output = Line; fn add(self, other: Self) -> Line { let min_start_x: f32; if &self.start.x > &other.start.x { min_start_x = other.start.x; } else { min_start_x = self.start.x; } let min_start_y: f32; if &self.start.x > &other.start.x { min_start_y = other.start.y; } else { min_start_y = self.start.y; } let max_end_x: f32; if &self.start.x < &other.start.x { max_end_x = other.start.x; } else { max_end_x = self.start.x; } let max_end_y: f32; if &self.start.x < &other.start.x { max_end_y = other.start.y; } else { max_end_y = self.start.y; } let p_a = Point::new(min_start_x, min_start_y); let p_b = Point::new(max_end_x, max_end_y); return Line::new(p_a, p_b); } }
and too prove that everything is working this is our main function
fn main() { println!("Points & Lines"); let point_a: Point = Point::new(0.0, 0.0); let point_b: Point = Point::new(0.0, 10.0); let line_a: Line = Line::new(point_a, point_b); println!("line a has a length of {:?}", line_a.length()); let point_c: Point = Point::new(10.0, 10.0); let point_d: Point = Point::new(10.0, 20.0); let line_b: Line = Line::new(point_c, point_d); println!("line b has a length of {:?}", line_b.length()); println!("are line a and b lengths equal? {:?}", line_a == line_b); println!( "is the mirror line's a length equal to line b {:?}", !line_a == line_b ); let line_c: Line = Line::new(point_a, point_d); let line_d: Line = Line::new(point_b, point_c); println!("line c has a length of {:?}", line_c.length()); println!("line d has a length of {:?}", line_d.length()); println!("is line c smaller than line b? {:?}", line_c < line_b); println!( "adding up lines give you a length of {:?}", (line_c + line_b).length() ); }
and our output
Points & Lines line a has a length of 10.0 line b has a length of 10.0 are line a and b lengths equal? true is the mirror line's a length equal to line b true line c has a length of 22.36068 line d has a length of 10.0 is line c smaller than line b? false adding up lines give you a length of 14.142136
I hope someone, out there, to find this piece useful. I certainly enjoyed writing it.
Top comments (0)