Hàm lấy giá trị
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 11 trên 61.
Với các trường riêng tư, code bên ngoài không thể truy cập trực tiếp vào dữ liệu của struct. Nhưng đôi khi bạn cần cho phép người khác đọc dữ liệu mà không thể thay đổi dữ liệu đó. Đây là lúc phương thức getter phát huy tác dụng.
Getter chỉ đơn giản là một phương thức công khai trả về tham chiếu đến một trường riêng tư:
// wallet.rs
pub struct Wallet {
balance: f64,
}
impl Wallet {
pub fn new(initial: f64) -> Wallet {
Wallet { balance: initial }
}
pub fn balance(&self) -> f64 {
self.balance
}
}
Phương thức balance() nhận &self (quyền truy cập chỉ đọc) và trả về giá trị của trường riêng tư. Trong Rust, hàm truy xuất (getter) thường được đặt tên theo chính trường dữ liệu: không cần tiền tố get_.
Giờ đây, code bên ngoài có thể đọc số dư thông qua phương thức:
// main.rs
mod wallet;
use wallet::Wallet;
fn main() {
let w = Wallet::new(100.0);
println!("Balance: {}", w.balance()); // Chạy được!
}
Với các trường chứa dữ liệu được sở hữu như String, bạn thường trả về một tham chiếu để tránh sao chép không cần thiết:
pub fn name(&self) -> &String {
&self.name
}
Hàm getter (getter) cho phép bạn đọc dữ liệu có kiểm soát mà vẫn bảo vệ trường đó. struct vẫn quản lý dữ liệu của mình: code bên ngoài có thể xem nhưng không thể sửa đổi.
Thử thách
DễHãy xây dựng một hệ thống hồ sơ người dùng để minh họa cách các phương thức getter cung cấp quyền đọc có kiểm soát đối với dữ liệu riêng tư.
Bạn sẽ tạo hai tệp để sắp xếp code:
profile.rs: Định nghĩa một structUserProfilevới hai trường riêng tư:username(String) vàage(u32). Bản thân struct phải là công khai, nhưng các trường phải giữ ở trạng thái riêng tư. Triển khai hàm khởi tạo công khainewnhận username và tuổi. Sau đó, thêm hai phương thức getter:username: trả về một tham chiếu đến username (&String)age: trả về giá trị tuổi (u32)
main.rs: Đưa module profile vào, tạo mộtUserProfilevà dùng các phương thức getter để in thông tin người dùng.
Hãy nhớ rằng trong Rust, getter thường được đặt tên theo chính trường đó: không cần tiền tố get_. Với các trường String, hãy trả về một tham chiếu để tránh sao chép không cần thiết.
Đầu ra của bạn phải theo đúng định dạng này:
Username: {username}
Age: {age}Ví dụ, nếu bạn tạo hồ sơ với username "alice" và tuổi 25, đầu ra sẽ là:
Username: alice
Age: 25Bạn sẽ nhận hai đầu vào: username và tuổi.
Tự làm thử
mod profile;
use profile::UserProfile;
fn main() {
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let username = input1.trim().to_string();
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let age: u32 = input2.trim().parse().expect("Failed to parse age");
// TODO: Tạo một UserProfile bằng hàm khởi tạo (constructor)
// TODO: Dùng các phương thức getter để in ra tên người dùng và tuổi
// Định dạng:
// Tên người dùng: {username}
// Tuổi: {age}
}
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