Menu
CoddyTech

Phương thức có thể thay đổi

Thuộc phần Lập trình hướng đối tượng trong hành trình Rust của Coddy. Bài học 3 trên 61.

Đôi khi, phương thức cần làm nhiều hơn là chỉ đọc dữ liệu. Chúng cần thay đổi dữ liệu. Để tạo phương thức có thể sửa đổi các trường của struct, ta dùng &mut self thay vì &self.

Từ khóa mut cho biết đây là một lượt mượn có thể thay đổi, cho phép phương thức sửa đổi trạng thái bên trong của instance:

struct Counter {
    value: i32,
}

impl Counter {
    fn increment(&mut self) {
        self.value += 1;
    }
    
    fn decrement(&mut self) {
        self.value -= 1;
    }
    
    fn get(&self) -> i32 {
        self.value
    }
}

Hãy lưu ý rằng increment và decrement dùng &mut self vì chúng thay đổi value, còn get dùng &self vì chỉ đọc dữ liệu.

Khi gọi các phương thức có thể thay đổi, bạn phải khai báo chính instance đó là có thể thay đổi:

fn main() {
    let mut counter = Counter { value: 0 };
    
    counter.increment();
    counter.increment();
    println!("{}", counter.get()); // 2
    
    counter.decrement();
    println!("{}", counter.get()); // 1
}

Nếu quên từ khóa mut khi tạo đối tượng, Rust sẽ không cho bạn gọi bất kỳ phương thức &mut self nào trên đối tượng đó. Nhờ vậy, bạn luôn biết khi nào dữ liệu có thể thay đổi.

challenge icon

Thử thách

Dễ

Tạo một struct BankAccount với một trường duy nhất: balance (i32).

Thêm một khối triển khai cho BankAccount với ba phương thức:

  • deposit: nhận &mut self và một amount: i32, cộng số tiền đó vào số dư
  • withdraw: nhận &mut self và một amount: i32, trừ số tiền đó khỏi số dư
  • get_balance: nhận &self và trả về số dư hiện tại dưới dạng i32

Bạn sẽ nhận ba đầu vào:

  • Dòng đầu tiên: số dư ban đầu (i32)
  • Dòng thứ hai: số tiền gửi vào (i32)
  • Dòng thứ ba: số tiền rút ra (i32)

Tạo một instance BankAccount có thể thay đổi với số dư ban đầu, sau đó gửi số tiền đã cho vào, rút số tiền đã cho ra và in số dư cuối cùng.

Định dạng đầu ra dự kiến:

{final_balance}

Tự làm thử

use std::io;

// TODO: Định nghĩa struct BankAccount tại đây


// TODO: Thêm khối lệnh triển khai cho BankAccount với các phương thức deposit, withdraw và get_balance


fn main() {
    let mut input = String::new();
    
    // Đọc số dư ban đầu
    io::stdin().read_line(&mut input).expect("Failed to read line");
    let initial_balance: i32 = input.trim().parse().expect("Invalid number");
    
    input.clear();
    
    // Đọc số tiền gửi
    io::stdin().read_line(&mut input).expect("Failed to read line");
    let deposit_amount: i32 = input.trim().parse().expect("Invalid number");
    
    input.clear();
    
    // Đọc số tiền rút
    io::stdin().read_line(&mut input).expect("Failed to read line");
    let withdraw_amount: i32 = input.trim().parse().expect("Invalid number");
    
    // TODO: Tạo instance BankAccount có thể thay đổi với initial_balance
    // TODO: Gọi deposit với deposit_amount
    // TODO: Gọi withdraw với withdraw_amount
    // TODO: In ra số dư cuối cùng bằng get_balance
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Rust online