Implementing Transaction Struct in Rust
Mục tiêu: Creating a Transaction struct with TransactionType enum, constructor, and display method in Rust.
Let’s start by creating the Transaction struct. This will represent each financial transaction in our application.
// Define an enumeration for transaction types
#[derive(Debug)]
enum TransactionType {
Income,
Expense,
}
// Implement the Transaction struct
#[derive(Debug)]
struct Transaction {
date: String,
description: String,
amount: f64,
transaction_type: TransactionType,
}
// Implement methods for the Transaction struct
impl Transaction {
// Constructor method to create a new Transaction
fn new(date: String, description: String, amount: f64, transaction_type: TransactionType) -> Self {
Transaction {
date,
description,
amount,
transaction_type,
}
}
// Method to display transaction details in a formatted way
fn display(&self) {
match self.transaction_type {
TransactionType::Income => println!("💰 Income: {} on {} - {}",
self.description,
self.date,
format_amount(self.amount)),
TransactionType::Expense => println!("💸 Expense: {} on {} - {}",
self.description,
self.date,
format_amount(self.amount)),
}
}
}
// Helper function to format amount with currency symbol
fn format_amount(amount: f64) -> String {
format!("${:.2}", amount)
}
Explanation:
- TransactionType Enum:
- We start by defining an enumeration
TransactionTypewith two variants:IncomeandExpense. This will help us categorize transactions easily. - Transaction Struct:
-
The
Transactionstruct has four fields:date: A String representing the date of the transactiondescription: A String describing the transactionamount: A floating-point number representing the transaction amounttransaction_type: An instance of the TransactionType enum
- Implementation Methods:
new(): A constructor method that creates and returns a new Transaction instance.display(): A method that prints the transaction details in a formatted way, showing different emojis for income and expense.- Helper Function:
format_amount(): A helper function that takes an amount and returns it as a formatted string with two decimal places and a dollar sign.
Example Usage:
fn main() {
let transaction = Transaction::new(
"2023-10-01".to_string(),
"Salary".to_string(),
5000.00,
TransactionType::Income,
);
transaction.display();
}
Next Steps:
- Implement Transaction Methods:
- Add more methods to the Transaction struct for operations like updating description, changing amount, etc.
- Transaction Type Methods:
- Add methods specific to transaction types (Income/Expense) using pattern matching.
- Validation:
- Add validation logic to ensure amounts are positive and dates are valid.
Best Practices:
- Encapsulation: Keep the data private and only expose necessary methods to interact with it
- Error Handling: Use Result types for operations that can fail
- Testing: Write unit tests for all methods
- Documentation: Add proper Rust documentation comments
Further Reading:
Implementing Methods for the Transaction Struct in Rust
Mục tiêu: Define and implement methods for the Transaction struct including a constructor, to_string method, and is_income method.
Implementing Methods for the Transaction Struct in Rust
Now that we’ve defined our Transaction struct in the previous task, let’s move on to implementing methods for this struct. Methods are essential for encapsulating behavior that operates on the struct’s data. For our Transaction struct, we’ll implement methods to format the transaction details and to determine if a transaction is income or expense.
Step-by-Step Implementation
- Defining Methods: We’ll define methods within an
implblock for ourTransactionstruct. - Formatting Transaction Details: Implement a
to_stringmethod to provide a human-readable representation of the transaction. - Determining Transaction Type: Implement an
is_incomemethod to check if the transaction is an income transaction.
Code Implementation
// Define an Enum for transaction types
enum TransactionType {
Income,
Expense,
}
// Define the Transaction struct
struct Transaction {
date: String,
description: String,
amount: f64,
transaction_type: TransactionType,
}
// Implement methods for Transaction
impl Transaction {
// Constructor method to create a new Transaction
fn new(date: String, description: String, amount: f64, transaction_type: TransactionType) -> Transaction {
Transaction {
date,
description,
amount,
transaction_type,
}
}
// Method to convert transaction to a formatted string
fn to_string(&self) -> String {
format!(
"Date: {}\nDescription: {}\nAmount: {:.2}$\nType: {}",
self.date,
self.description,
self.amount,
match self.transaction_type {
TransactionType::Income => "Income",
TransactionType::Expense => "Expense",
}
)
}
// Method to check if the transaction is income
fn is_income(&self) -> bool {
matches!(self.transaction_type, TransactionType::Income)
}
}
Explanation
- Enum Definition: We’ve defined an
enumcalledTransactionTypewith two variants:IncomeandExpense. This will be used to categorize each transaction. - Struct Definition: The
Transactionstruct has four fields:date,description,amount, andtransaction_type. - Constructor Method (
new): - This is a common pattern in Rust to provide a way to construct instances of a struct.
- It takes four parameters:
date,description,amount, andtransaction_type. - Returns a new instance of
Transaction. - to_string Method:
- This method returns a formatted string representation of the transaction.
- Uses
format!macro for string interpolation. - Includes all relevant details of the transaction in a readable format.
- is_income Method:
- This method checks if the transaction type is
Income. - Uses pattern matching with
matches!macro to check the variant oftransaction_type. - Returns
trueif it’sIncome, otherwisefalse.
Example Usage
fn main() {
// Create a new income transaction
let income_tx = Transaction::new(
"2023-10-01".to_string(),
"Salary".to_string(),
5000.00,
TransactionType::Income,
);
// Create a new expense transaction
let expense_tx = Transaction::new(
"2023-10-02".to_string(),
"Groceries".to_string(),
120.00,
TransactionType::Expense,
);
// Print transaction details
println!("Income Transaction:\n{}", income_tx.to_string());
println!("\nExpense Transaction:\n{}", expense_tx.to_string());
// Check transaction types
println!("\nIs income_tx income? {}", income_tx.is_income());
println!("Is expense_tx income? {}", expense_tx.is_income());
}
Output
Income Transaction:
Date: 2023-10-01
Description: Salary
Amount: 5000.00$
Type: Income
Expense Transaction:
Date: 2023-10-02
Description: Groceries
Amount: 120.00$
Type: Expense
Is income_tx income? true
Is expense_tx income? false
Next Steps
Now that we’ve implemented the core struct and its methods, we can move on to:
- Implementing functions to add/remove transactions
- Integrating these methods with our future file I/O operations
- Using these methods in our command-line interface
Further Reading
Creating a Transaction Type Enum in Rust
Mục tiêu: Defines an Enum for transaction types with Income and Expense variants and implements a method to convert the Enum to a string.
Let’s create an Enum for transaction types in Rust. Enums are useful for defining a set of named constants. In this case, we’ll create a TransactionType enum with two variants: Income and Expense.
// Define an Enum for transaction types
enum TransactionType {
Income,
Expense,
}
// Implement methods for the TransactionType enum if needed
impl TransactionType {
fn get_type(&self) -> &str {
match self {
TransactionType::Income => "Income",
TransactionType::Expense => "Expense",
}
}
}
This enum will be used in our Transaction struct to represent whether a transaction is income or expense. The get_type() method returns a string representation of the transaction type, which will be useful for displaying information to the user later.
Explanation:
- Enum Definition: We define an enum called TransactionType with two variants: Income and Expense. This restricts the transaction type to only these two possibilities, making our code safer and more predictable.
- Enum Methods: We implement a method get_type() that returns a string representation of the enum variant. This is useful for converting the enum variants to strings when displaying information to the user.
- Type Safety: Using an enum ensures type safety - we can’t have any other type of transaction besides Income or Expense, which helps catch errors early in the development process.
Next Steps:
Now that we’ve defined the transaction type enum, we can move on to implementing methods for the Transaction struct. We’ll use this TransactionType enum as one of the fields in our Transaction struct to represent the type of transaction.