Built-in traits and operator overloading

The Rust standard library is packed with traits, which are used all over the place. For example, there are traits for which the compiler is capable of providing a basic implementation with a #[derive] attribute, as we saw in the section on Traits:

The next chapter shows an example of how to implement the following three traits:

      pub trait Add<RHS = Self> { 
           type Output; 
  
            fn add(self, rhs: RHS) -> Self::Output; 
      }

So the add method and the trait item Output must both be implemented. The code impl_add.rs shows an implementation of the Add trait:

struct AType { 
    value: i32, 
} 
 
impl AType { 
    fn new(value: i32) -> AType { 
        AType { value: value } 
    } 
} 
 
impl Add for AType { 
    type Output = AType; 
 
    fn add(self, other: AType) -> AType { 
        AType { value: self.value + other.value } 
    } 
} 
 
fn main() { 
    let at1 = AType{ value: 7 }; 
    let at2 = AType{ value: 42 }; 
    let at3 = at1.add(at2); 
    println!("{:?}", at3); 
    let at4 = AType{ value: 2 }; 
    let at5 = AType{ value: 108 }; 
    let at6 = at4 + at5; 
    println!("{:?}", at6); 
} 
    AType { value: 49 }
    AType { value: 110 }  
Note that we can use it as a + operator or an add method. A lot of other traits can also be used to overload operators, such as Sub(-), Mul(*), Deref (*v), Index([]), and so on.

In the section Iterators we described how an iterator works and used it on ranges and arrays. In fact an iterator is also defined as a trait in Rust in std::iter::Iterator. From the docs for iterator (see http://doc.rust-lang.org/std/iter/trait.Iterator.html) we see that we only need to define the next() method, which advances the iterator to return the next value as an Option type. When the next() method is implemented for the type of your object, we can then use a for in loop to iterate over the object.