
Impl blocks for enums
We can also provide implementations for enums. For example, consider a payments library built in Rust, which exposes a single API called pay:
// enum_methods.rs
enum PaymentMode {
Debit,
Credit,
Paypal
}
// Bunch of dummy payment handlers
fn pay_by_credit(amt: u64) {
println!("Processing credit payment of {}", amt);
}
fn pay_by_debit(amt: u64) {
println!("Processing debit payment of {}", amt);
}
fn paypal_redirect(amt: u64) {
println!("Redirecting to paypal for amount: {}", amt);
}
impl PaymentMode {
fn pay(&self, amount: u64) {
match self {
PaymentMode::Debit => pay_by_debit(amount),
PaymentMode::Credit => pay_by_credit(amount),
PaymentMode::Paypal => paypal_redirect(amount)
}
}
}
fn get_saved_payment_mode() -> PaymentMode {
PaymentMode::Debit
}
fn main() {
let payment_mode = get_saved_payment_mode();
payment_mode.pay(512);
}
The preceding code has a method called get_saved_payment_mode(), which returns a user's saved payment mode. This can either be a Credit Card, Debit Card, or Paypal. This is best modeled as an enum, where different payment methods can be added as its variants. The library then provides us with a single pay() method to which we can conveniently provide an amount to pay. This method determines which variant of the enum it is and dispatches methods accordingly to the correct payment service provider, without the library consumer worrying about checking which payment method to use.
Enums are also widely used for modeling state machines, and when combined with match statements, they make state transition code very concise to write. They are also used to model custom error types. When enum variants don't have any data associated with them, they can be used like C enums, where the variants implicitly have integer values starting with 0, but can also be manually tagged with integer (isize) values. This is useful when interacting with foreign C libraries.