OOP Bài 3: Các khái niệm nền tảng - Lớp (Class) và Đối tượng (Object)
1. Lớp (Class) là gì? Nó là "Bản thiết kế"
Class KHÔNG phải là dữ liệu thực tế. Nó là một cái khuôn (template), một bản vẽ kỹ thuật (blueprint) định nghĩa trước những gì một thực thể sẽ có.
Bản thân Class không chiếm dụng dung lượng bộ nhớ đáng kể để lưu trữ dữ liệu nghiệp vụ, và bạn không thể trực tiếp yêu cầu một Class thực hiện thao tác (trừ khi dùng Static - sẽ học ở bài sau).
- Ví dụ thực chiến: Trong dự án metro AFC, trước khi lắp đặt hàng loạt máy bán vé tự động (Ticket Vending Machine - TVM), các kỹ sư phải vẽ ra một "Bản thiết kế TVM". Bản thiết kế này quy định rõ: máy phải có khe nhận tiền, có màn hình cảm ứng, có cuộn vé bên trong (Thuộc tính) và phải có khả năng nhả vé, thối tiền (Phương thức). Bản thiết kế đó chính là Class. Bản thân tờ giấy thiết kế không thể bán vé cho khách.
2. Đối tượng (Object) là gì? Nó là "Thực thể sống"
Object là sản phẩm thực tế được đúc ra từ Class. Khi chương trình chạy, Object được sinh ra, được cấp phát không gian trong bộ nhớ RAM, chứa dữ liệu thật và có thể thực thi các hành động thực tế. Quá trình tạo ra một Object từ một Class được gọi là Khởi tạo (Instantiation).
- Ví dụ thực chiến: Từ "Bản thiết kế TVM" ở trên, nhà máy sản xuất ra 2 chiếc máy thật. Một cái đặt ở Ga số 1, một cái đặt ở Ga số 2. Hai chiếc máy cứng cáp, sờ chạm được này chính là Object.
3. Mối quan hệ giữa Class và Object
- Mối quan hệ 1 - N: Một Class duy nhất có thể sinh ra hàng triệu Object khác nhau.
- Tính độc lập về trạng thái (State): Các Object sinh ra từ cùng một Class có cấu trúc giống hệt nhau, nhưng dữ liệu bên trong chúng là hoàn toàn độc lập. Nếu khách nhét 100.000đ vào cái máy ở Ga số 1, thì tiền trong máy số 1 tăng lên, máy ở Ga số 2 không hề bị ảnh hưởng.
4. Code minh họa sự độc lập của Object
Đoạn code PHP (hoặc TypeScript, Java đều có tư duy tương tự) mô phỏng lại ví dụ máy bán vé tự động:
// 1. CLASS: Đóng vai trò là Bản vẽ thiết kế
class TicketVendingMachine {
// Thuộc tính (Dữ liệu máy sẽ giữ)
private $machineId;
private $stationName;
private $cashInside; // Số tiền máy đang có
// Constructor: Hàm chạy ngay khi cái máy được lắp đặt
public function __construct($id, $station) {
$this->machineId = $id;
$this->stationName = $station;
$this->cashInside = 0; // Máy mới ra lò, chưa có tiền
}
// Phương thức (Hành vi của máy)
public function receiveCash($amount) {
$this->cashInside += $amount;
echo "Máy [{$this->machineId}] tại {$this->stationName} vừa nhận: {$amount} VNĐ.\n";
}
public function checkCash() {
echo "=> Tổng tiền trong máy [{$this->machineId}]: {$this->cashInside} VNĐ.\n\n";
}
}
// ==========================================
// 2. OBJECTS: Các máy bán vé thực tế được cấp RAM và đưa vào hoạt động
// Dùng từ khóa 'new' để đúc Object từ Class
// Đúc máy số 1, đặt tại ga Bến Thành
$machineBenThanh = new TicketVendingMachine("TVM_01", "Ga Bến Thành");
// Đúc máy số 2, đặt tại ga Suối Tiên
$machineSuoiTien = new TicketVendingMachine("TVM_02", "Ga Suối Tiên");
// ==========================================
// 3. CHỨNG MINH TÍNH ĐỘC LẬP
// Khách hàng nhét 50.000 vào máy Bến Thành
$machineBenThanh->receiveCash(50000);
// Khách hàng nhét 20.000 vào máy Suối Tiên
$machineSuoiTien->receiveCash(20000);
// Kiểm tra lại bộ đếm tiền của từng máy
$machineBenThanh->checkCash(); // Báo có 50.000
$machineSuoiTien->checkCash(); // Báo có 20.000
Bài học rút ra:
$machineBenThanhvà$machineSuoiTienlà hai Object riêng biệt nằm trên 2 vùng RAM khác nhau. ClassTicketVendingMachinechỉ là cái khung định hình lên chúng. Bằng cách chia nhỏ hệ thống thành các Object độc lập như thế này, bạn có thể thiết lập các luồng xử lý đồng thời (concurrency) rất hiệu quả vì dữ liệu không dẫm chân lên nhau.
All rights reserved