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,
}
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,
}
}
}
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);
}
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);
}
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)