OOP Bài 14: Phương thức tĩnh (Static Methods) và những ranh giới cấm kỵ
1. Phương thức tĩnh là gì?
Phương thức tĩnh là những hàm được gắn từ khóa static. Điểm tối thượng của nó là: Bạn có thể gọi nó chạy ngay lập tức thông qua tên Class, mà tuyệt đối không cần dùng từ khóa new để khởi tạo Object.
Nó đóng vai trò như những "tiện ích công cộng" của hệ thống.
class MathHelper {
// Phương thức tĩnh
public static function add($a, $b) {
return $a + $b;
}
}
// Gọi trực tiếp, không cần: $math = new MathHelper();
$result = MathHelper::add(10, 5);
2. Hai hạn chế chí mạng (Quy luật vật lý của bộ nhớ)
Bởi vì Phương thức tĩnh có thể được gọi khi chưa có bất kỳ Object nào được sinh ra, nó phải tuân thủ 2 đạo luật sắt đá sau:
A. Tuyệt đối không được dùng từ khóa $this (hoặc this)
Từ khóa $this đóng vai trò là "con trỏ" chỉ ngược lại cái Object đang thực thi nó (nằm trên vùng nhớ Heap). Nhưng khi gọi hàm tĩnh, Object đó chưa hề tồn tại. Dùng $this trong hàm tĩnh chẳng khác nào chỉ tay vào không khí. Trình biên dịch sẽ báo lỗi Fatal Error ngay lập tức.
B. Hàm tĩnh không thể gọi Hàm thường hoặc Thuộc tính thường
Người âm không thể nói chuyện với người dương. Một hàm tĩnh (nằm ở vùng nhớ chung) không thể nào biết được thuộc tính riêng $balance hay hàm $ticket->tapIn() của hàng triệu Object khác nhau đang chứa giá trị gì.
Quy tắc: Bên trong hàm tĩnh, chỉ được phép gọi các biến tĩnh (qua
self::) hoặc các hàm tĩnh khác.
Mã nguồn chứng minh giới hạn:
class PaymentService {
private $gatewayName = "VNPay"; // Thuộc tính thường
private static $feePercent = 2.5; // Thuộc tính tĩnh
// PHƯƠNG THỨC THƯỜNG (Có $this)
public function getGateway() {
return $this->gatewayName; // HỢP LỆ
return self::$feePercent; // HỢP LỆ (Hàm thường có thể thấy đồ tĩnh)
}
// PHƯƠNG THỨC TĨNH (Không có $this)
public static function calculateFee($amount) {
// LỖI CHẾT NGƯỜI: $this không tồn tại ở đây!
// echo $this->gatewayName;
// CHỈ HỢP LỆ khi tương tác với đồ tĩnh
return $amount * (self::$feePercent / 100);
}
}
3. Khi nào bạn NÊN dùng Phương thức tĩnh?
Dù có nhiều hạn chế, Phương thức tĩnh vẫn là vũ khí cực mạnh nếu dùng đúng ngữ cảnh:
- Làm các lớp Tiện ích (Utility/Helper Classes): Xử lý chuỗi, định dạng ngày tháng, tính toán toán học (ví dụ:
StringHelper::slugify(),DateUtil::now()). Đây là các hàm thuần túy (Pure functions) – chỉ nhận input và nhả ra output, không cần lưu trữ trạng thái. - Factory Methods: Dùng hàm tĩnh để tạo ra các Object một cách rõ ràng (ví dụ:
Ticket::createVipTicket()).
4. Tại sao Kiến trúc sư hệ thống lại "ghét" lạm dụng Static Methods?
Nếu bạn đang build các hệ thống backend lớn, thiết kế Clean Architecture hoặc Microservices, lạm dụng hàm tĩnh bị coi là một Anti-pattern (Mẫu phản thiết kế) vì 2 lý do:
- Tạo ra sự gắn kết chặt (Tight Coupling): Nếu Class
OrderServicegọi trực tiếpPaymentHelper::process(), nó đã bị khóa chặt vào Class này. Không thể dùng Dependency Injection (DI) để thay thếPaymentHelperbằng một cái khác. - Kẻ thù của Unit Test: Bạn không thể "Mock" (làm giả) các phương thức tĩnh một cách dễ dàng trong các framework testing (như PHPUnit, Testify trong Go). Điều này khiến việc viết test tự động trở thành cực hình.
Chốt lại: Đừng biến các Class OOP thành một cái túi chứa các hàm rời rạc (POP) bằng cách gắn
staticcho tất cả mọi thứ chỉ vì "lười viết chữ new". Hãy để các Object sống và giao tiếp với nhau.
All rights reserved