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.
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 selfvà mộtamount: i32, cộng số tiền đó vào số dưwithdraw: nhận&mut selfvà mộtamount: i32, trừ số tiền đó khỏi số dưget_balance: nhận&selfvà trả về số dư hiện tại dưới dạngi32
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
}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
1Phương thức và hành vi
Nhập môn khối triển khaiTham số selfPhương thức có thể thay đổiHàm liên kếtNhiều khối triển khaiNối chuỗi phương thứcÔn tập: thao tác với hình chữ nhật4Dự án: Thú cưng ảo
Định nghĩa thú cưngCho thú cưng ăn7Các trait tiêu chuẩn
Trait DebugTrait DisplayClone và CopyCác trait so sánh bằngÔn tập: Điểm có thể in ra2Tính đóng gói và module
Kiến thức cơ bản về moduleTừ khóa publicTrường riêng tưHàm lấy giá trịHàm thiết lập giá trịÔn tập: tủ khóa an toàn5Kiểu tổng quát
Cấu trúc tổng quátPhương thức tổng quátNhiều kiểu tổng quátHàm tổng quátÔn tập: điểm tọa độTự luyện tập: Trình biên dịch Rust online