Bạn muốn hiểu rõ cách kiểm soát quyền truy cập trong lập trình PHP hướng đối tượng? Khám phá Public, Protected, Private là gì, sự khác biệt giữa chúng và cách áp dụng hiệu quả vào thuộc tính và phương thức. Bài viết này sẽ hướng dẫn bạn chi tiết với các ví dụ cụ thể để xây dựng mã nguồn an toàn và dễ bảo trì hơn.
Trong lập trình hướng đối tượng (OOP) với PHP, việc kiểm soát quyền truy cập vào các thuộc tính (properties) và phương thức (methods) của một lớp (class) là vô cùng quan trọng. PHP cung cấp ba từ khóa quyền truy cập chính: public
, protected
, và private
. Hiểu rõ và sử dụng đúng các từ khóa này giúp chúng ta xây dựng mã nguồn an toàn hơn, dễ bảo trì hơn và tuân thủ các nguyên tắc thiết kế tốt.
Bài viết này sẽ đi sâu vào từng loại quyền truy cập, cùng với các ví dụ minh họa để bạn có thể nắm vững cách sử dụng chúng.
Khi một thuộc tính hoặc phương thức được khai báo là public
, điều đó có nghĩa là nó có thể được truy cập từ bất cứ đâu:
Đây là quyền truy cập mặc định nếu bạn không chỉ định bất kỳ từ khóa quyền truy cập nào (mặc dù tốt nhất là nên chỉ định rõ ràng để mã nguồn dễ đọc hơn).
public
:
<?php
class Car {
public $brand;
public $model;
public function __construct($brand, $model) {
$this->brand = $brand;
$this->model = $model;
}
public function getCarInfo() {
return "Brand: " . $this->brand . ", Model: " . $this->model;
}
}
$myCar = new Car("Toyota", "Camry");
// Truy cập thuộc tính public từ bên ngoài
echo $myCar->brand; // Output: Toyota
echo "<br>";
// Gọi phương thức public từ bên ngoài
echo $myCar->getCarInfo(); // Output: Brand: Toyota, Model: Camry
echo "<br>";
// Thay đổi thuộc tính public từ bên ngoài
$myCar->brand = "Honda";
echo $myCar->getCarInfo(); // Output: Brand: Honda, Model: Camry
?>
public
?protected
hoặc private
cho dữ liệu thực và cung cấp getter/setter public
).Khi một thuộc tính hoặc phương thức được khai báo là protected
, nó chỉ có thể được truy cập:
Nó không thể được truy cập từ bên ngoài lớp thông qua một đối tượng của lớp đó.
protected
:
<?php
class Vehicle {
protected $maxSpeed;
public function __construct($maxSpeed) {
$this->maxSpeed = $maxSpeed;
}
protected function getMaxSpeedInfo() {
return "Max Speed: " . $this->maxSpeed . " km/h";
}
}
class SportsCar extends Vehicle {
public function getSportsCarDetails() {
// Truy cập thuộc tính protected từ lớp con
return "This is a sports car with " . $this->getMaxSpeedInfo();
}
public function accelerate() {
// Gọi phương thức protected từ lớp con
echo "Accelerating... " . $this->getMaxSpeedInfo();
}
}
// $myVehicle = new Vehicle(200);
// echo $myVehicle->maxSpeed; // Lỗi: Cannot access protected property Vehicle::$maxSpeed
// echo $myVehicle->getMaxSpeedInfo(); // Lỗi: Call to protected method Vehicle::getMaxSpeedInfo()
$mySportsCar = new SportsCar(300);
echo $mySportsCar->getSportsCarDetails(); // Output: This is a sports car with Max Speed: 300 km/h
echo "<br>";
$mySportsCar->accelerate(); // Output: Accelerating... Max Speed: 300 km/h
?>
protected
?Khi một thuộc tính hoặc phương thức được khai báo là private
, nó chỉ có thể được truy cập:
Nó không thể được truy cập:
Đây là quyền truy cập hạn chế nhất, đảm bảo tính đóng gói (encapsulation) cao nhất.
private
:
<?php
class BankAccount {
private $accountNumber;
private $balance;
public function __construct($accountNumber, $initialBalance) {
$this->accountNumber = $accountNumber;
$this->balance = $initialBalance;
$this->logTransaction("Account created with initial balance: " . $initialBalance);
}
private function logTransaction($message) {
// Phương thức private chỉ dùng nội bộ
echo "LOG: " . $message . " at " . date("Y-m-d H:i:s") . "<br>";
}
public function deposit($amount) {
if ($amount > 0) {
$this->balance += $amount;
$this->logTransaction("Deposited: " . $amount . ", New balance: " . $this->balance);
} else {
$this->logTransaction("Attempted to deposit invalid amount: " . $amount);
}
}
public function getBalance() {
return $this->balance;
}
}
class SavingsAccount extends BankAccount {
// public function testPrivate() {
// // Lỗi: Cannot access private property BankAccount::$balance
// // echo $this->balance;
// // Lỗi: Call to private method BankAccount::logTransaction()
// // $this->logTransaction("Attempt to log from SavingsAccount");
// }
}
$myAccount = new BankAccount("123456789", 1000);
// echo $myAccount->accountNumber; // Lỗi: Cannot access private property BankAccount::$accountNumber
// $myAccount->logTransaction("Test external log"); // Lỗi: Call to private method BankAccount::logTransaction()
$myAccount->deposit(500); // Hoạt động bình thường
echo "Current balance: " . $myAccount->getBalance();
echo "<br>";
$savings = new SavingsAccount("987654321", 5000);
// $savings->testPrivate(); // Sẽ gây lỗi nếu uncomment
?>
private
?Quyền truy cập | Từ cùng lớp | Từ lớp kế thừa | Từ bên ngoài đối tượng |
---|---|---|---|
public |
Có | Có | Có |
protected |
Có | Có | Không |
private |
Có | Không | Không |
private
: Một quy tắc chung trong OOP là "mặc định là private
". Bắt đầu với private
cho tất cả các thuộc tính và phương thức, sau đó nâng cấp lên protected
hoặc public
khi thực sự cần thiết. Điều này giúp tăng cường tính đóng gói và giảm sự phụ thuộc giữa các thành phần.private
để bảo vệ dữ liệu nội bộ của đối tượng. Thay vì truy cập trực tiếp các thuộc tính, hãy cung cấp các phương thức public
(getter/setter) để kiểm soát cách dữ liệu được đọc và ghi. Điều này cho phép bạn thêm logic kiểm tra hợp lệ hoặc xử lý dữ liệu khi cần.protected
là lựa chọn lý tưởng khi bạn muốn chia sẻ một số chức năng hoặc dữ liệu với các lớp con mà không muốn chúng bị truy cập công khai.public
định nghĩa giao diện (API) của lớp bạn. Chúng là cách mà các phần khác của ứng dụng tương tác với đối tượng của bạn.Việc nắm vững và áp dụng đúng các từ khóa public
, protected
, và private
là nền tảng của lập trình hướng đối tượng hiệu quả trong PHP. Chúng cho phép bạn kiểm soát chặt chẽ quyền truy cập vào các thành viên của lớp, tăng cường tính đóng gói, dễ dàng quản lý mã nguồn và xây dựng các ứng dụng mạnh mẽ, linh hoạt và dễ bảo trì hơn. Hãy luôn suy nghĩ về mức độ hiển thị cần thiết cho từng thuộc tính và phương thức khi thiết kế các lớp của bạn.