Build a BankAccount class that keeps its balance private and lets other code change it only through methods that check the rules. This is encapsulation: the object protects its own data.
Private balance. The struct's field balance has no pub, so code outside the module cannot touch it. Methods live in an impl BankAccount block; ones that change the account take &mut self, read-only ones take &self.
What the class must have (Rust):
- The associated function
BankAccount::new(initial_balance: f64) -> BankAccount: creates an account that starts with the given balance. fn deposit(&mut self, amount: f64): addsamountto the balance. Ifamountis zero or negative, do nothing (no error, the balance stays the same).fn withdraw(&mut self, amount: f64) -> bool: ifamountis zero or negative, or larger than the balance, change nothing and returnfalse. Otherwise subtract it from the balance and returntrue. Withdrawing exactly the whole balance is allowed (the balance becomes 0).fn get_balance(&self) -> f64: returns the current balance. It is the only way for outside code to read it.
In Rust you also write mainFunction(), the driver, as the last steps of the lesson. println! prints the f64 value 120.0 as 120.
The driver. You write the driver last, in mainFunction(). It runs these checks:
fn mainFunction() {
let mut account = BankAccount::new(100.0);
account.deposit(50.0);
account.withdraw(30.0);
account.withdraw(200.0);
println!("Balance: {}", account.get_balance());
account.deposit(-20.0);
account.deposit(0.0);
account.withdraw(-5.0);
println!("Balance: {}", account.get_balance());
if account.withdraw(120.0) {
println!("Withdrew all");
}
println!("Balance: {}", account.get_balance());
if !account.withdraw(1.0) {
println!("Rejected");
}
}
Walk through it: start with 100, deposit 50 (150), withdraw 30 (120), withdraw 200 is refused (still 120). Then deposit -20, deposit 0 and withdraw -5 are all ignored (still 120). Withdrawing 120 succeeds and empties the account, so the balance is 0, and withdrawing 1 more is refused.
Expected output:
Balance: 120
Balance: 120
Withdrew all
Balance: 0
Rejected
Both
deposit and withdraw start with a guard that rejects amount <= 0. Write the guard first, then the change to the balance.
BankAccount { balance: initial_balance }
if amount <= 0.0 || amount > self.balance { return false; }, then self.balance -= amount; and true as the last expression.
struct BankAccount {
balance: f64,
}
impl BankAccount {
fn new(initial_balance: f64) -> BankAccount {
BankAccount {
balance: initial_balance,
}
}
fn deposit(&mut self, amount: f64) {
if amount <= 0.0 {
return;
}
self.balance += amount;
}
fn withdraw(&mut self, amount: f64) -> bool {
if amount <= 0.0 || amount > self.balance {
return false;
}
self.balance -= amount;
true
}
fn get_balance(&self) -> f64 {
self.balance
}
}
fn mainFunction() {
let mut account = BankAccount::new(100.0);
account.deposit(50.0);
account.withdraw(30.0);
account.withdraw(200.0);
println!("Balance: {}", account.get_balance());
account.deposit(-20.0);
account.deposit(0.0);
account.withdraw(-5.0);
println!("Balance: {}", account.get_balance());
if account.withdraw(120.0) {
println!("Withdrew all");
}
println!("Balance: {}", account.get_balance());
if !account.withdraw(1.0) {
println!("Rejected");
}
}
Free plan: 30 tutor messages. Premium is unlimited.
