DEV Community

Cover image for Rust Overload Add operator
Joaquín Caro
Joaquín Caro

Posted on • Updated on

Rust Overload Add operator

Can you imagine being able to perform arithmetic operations with your own types in java? to have two Money instances and add between them?
Well in Rust it is possible! Let's see a simple example of how to implement it.

For our example, we want to be able to add amounts of the same currency, for that we will create the ValueObject Money

#[derive(Debug, PartialEq)]
enum Currency {DOLLAR, EURO}

#[derive(Debug, PartialEq)]
struct Money {
    currency: Currency,
    amount: u8,
}
Enter fullscreen mode Exit fullscreen mode

Now what we would like is to be able to add Money without having to add the internal amount and creating a Money again.
In Rust it is as simple as implementing the std :: ops :: Add trait for our struct:

impl std::ops::Add for Money {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        Money {
            currency: self.currency,
            amount: self.amount + other.amount,
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

in this way we could already add Money to each other:

#[test]
fn should_add_money_with_same_currency() {
    let ten_dollars = Money {
        currency: Currency::DOLLAR,
        amount: 10,
    };
    let five_dollars = Money {
        currency: Currency::DOLLAR,
        amount: 5,
    };
    let fifteen = Money {
        currency: Currency::DOLLAR,
        amount: 15,
    };
    assert_eq!(ten_dollars + five_dollars, 
               fifteen);
}
Enter fullscreen mode Exit fullscreen mode

But of course ... what if we are adding dollars to euros? with this implementation the sum would be incorrect, so in our case what we want is that the result of the sum is a Result Type.
For that case, we are going to change our implementation of the Add so that the output becomes a Result instead of a Money

impl std::ops::Add for Money {
    type Output = Result<Self, &'static str>;

    fn add(self, money: Self) -> Self::Output {
        if  money.currency != self.currency {
            return Err("Can not operate with different currencies")
        }
        Ok(Money {
            currency: self.currency,
            amount: self.amount + money.amount,
        })
    }
}

#[test]
fn should_add_money_with_same_currency() {
    let ten_dollars = Money {
        currency: Currency::DOLLAR,
        amount: 10,
    };
    let five_dollars = Money {
        currency: Currency::DOLLAR,
        amount: 5,
    };
    let fifteen = ten_dollars + five_dollars;
    assert!(fifteen.is_ok(),true);
    assert_eq!(fifteen.ok().unwrap().amount,15);
}

#[test]
fn should_not_allow_add_money_with_different_currency() {
    let ten_dollars = Money {
        currency: Currency::DOLLAR,
        amount: 10,
    };
    let five_euros = Money {
        currency: Currency::EURO,
        amount: 5,
    };
    let fifteen = ten_dollars + five_euros;
    assert!(fifteen.is_err(),true);
}
Enter fullscreen mode Exit fullscreen mode

Add operator It is not the only operator that we have available to overload it in rust, the complete list can be seen in the documentation

The complete code example can be downloaded at github or run it on Rust Playground

Originally published at blog.joaquin-caro.es

Top comments (0)