OOP Bài 4: Cấu trúc của một Class: Thuộc tính và Phương thức
1. Thuộc tính (Attribute / Property / Field) - Nơi lưu giữ "Trạng thái"
Thuộc tính thực chất là các biến (variables) được khai báo bên trong một Class. Nhiệm vụ của chúng là lưu trữ dữ liệu đặc trưng cho từng Object được sinh ra từ Class đó.
- Bản chất thực chiến: Nếu bạn ánh xạ một Class xuống cơ sở dữ liệu (thông qua ORM như Prisma, Eloquent, hoặc Hibernate), thì Thuộc tính thường tương ứng với các cột (columns) trong một bảng (table) của Database.
- Trạng thái (State): Giá trị của các thuộc tính tại một thời điểm cụ thể tạo nên "trạng thái" của Object đó. Trạng thái này có thể thay đổi trong suốt vòng đời của Object (từ lúc được khởi tạo bằng
newcho đến khi bị Garbage Collector dọn dẹp). - Ví dụ thực chiến: Trong hệ thống kiểm soát vé AFC, đối tượng
SmartCard(Thẻ quẹt đi tàu) sẽ có các thuộc tính:$cardNumber(Mã thẻ),$balance(Số dư),$cardStatus(Trạng thái: Khóa/Mở),$lastTapInStation(Ga vừa quẹt thẻ vào).
2. Phương thức (Method) - Cỗ máy thực thi "Nghiệp vụ"
Phương thức thực chất là các hàm (functions) được định nghĩa bên trong một Class. Điểm khác biệt lớn nhất giữa một "Hàm tự do" (trong POP) và "Phương thức" (trong OOP) là: Phương thức có ngữ cảnh.
Phương thức sinh ra để thao tác trực tiếp lên các Thuộc tính của chính Object chứa nó. Nó định nghĩa những hành vi, những gì Object đó có thể làm hoặc những gì hệ thống có thể yêu cầu Object đó làm.
Phân loại phổ biến trong thực tế:
- Mutators / Accessors: Các phương thức đơn giản chỉ dùng để lấy ra (Getters) hoặc gán lại (Setters) giá trị cho Thuộc tính.
- Business Logic Methods: Các phương thức chứa luồng nghiệp vụ phức tạp (ví dụ:
calculateFare(),processGateLogic()).
3. Giải phẫu qua Mã nguồn thực chiến (PHP)
Cấu trúc một Class SmartCard thể hiện sự tương tác chặt chẽ giữa Thuộc tính và Phương thức:
class SmartCard {
// ==========================================
// 1. VÙNG THUỘC TÍNH (ATTRIBUTES)
// Nơi khai báo dữ liệu mà thẻ cần quản lý
// ==========================================
private $cardNumber;
private $balance;
private $status; // 'active', 'blocked'
private $isTappedIn; // Đang ở trong ga hay ngoài ga (true/false)
// (Hàm khởi tạo Constructor - sẽ học sâu ở bài 8)
public function __construct($cardNumber, $initialBalance) {
$this->cardNumber = $cardNumber;
$this->balance = $initialBalance;
$this->status = 'active';
$this->isTappedIn = false;
}
// ==========================================
// 2. VÙNG PHƯƠNG THỨC (METHODS)
// Nơi định nghĩa các hành vi nghiệp vụ của thẻ
// ==========================================
// Hành vi nạp tiền (Thao tác thay đổi Thuộc tính $balance)
public function topUp($amount) {
if ($this->status === 'blocked') {
throw new Exception("Thẻ đã bị khóa, không thể nạp tiền.");
}
$this->balance += $amount;
return true;
}
// Hành vi quẹt thẻ vào ga
public function tapIn() {
if ($this->status !== 'active') {
echo "[{$this->cardNumber}] Thẻ không hợp lệ!\n";
return false;
}
if ($this->isTappedIn) {
echo "[{$this->cardNumber}] Lỗi: Thẻ đang trong trạng thái chưa tap-out!\n";
return false;
}
$this->isTappedIn = true; // Cập nhật trạng thái
echo "[{$this->cardNumber}] Tap-In thành công. Cửa mở!\n";
return true;
}
// Hành vi kiểm tra số dư (Chỉ đọc Thuộc tính, không sửa đổi)
public function getBalance() {
return $this->balance;
}
}
4. Quy tắc "Gắn kết" (Cohesion) cốt lõi
Một trong những dấu hiệu của một cấu trúc Class tồi (Bad Smell Code) là: Có những Phương thức không bao giờ đụng đến bất kỳ Thuộc tính nào của Class đó.
Nếu một phương thức không cần đọc hay ghi vào thuộc tính nội tại của Object, rất có thể phương thức đó đang bị đặt nhầm chỗ, hoặc nó nên là một hàm độc lập, hoặc một phương thức tĩnh (Static Method). Phương thức và Thuộc tính trong một Class phải có sự gắn kết chặt chẽ (High Cohesion) - Phương thức sinh ra là để phục vụ cho Thuộc tính.
All rights reserved